deepagents-cli 0.0.53__tar.gz → 0.0.54__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.53 → deepagents_cli-0.0.54}/CHANGELOG.md +14 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/PKG-INFO +2 -2
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/_version.py +1 -1
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/app.py +121 -16
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/config.py +20 -8
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/main.py +90 -14
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/model_config.py +12 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/server.py +21 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/server_graph.py +20 -9
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/sessions.py +42 -3
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/ui.py +2 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/widgets/status.py +5 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/widgets/thread_selector.py +261 -13
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/widgets/update_progress.py +3 -1
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/frontend/package-lock.json +9 -9
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/pyproject.toml +2 -2
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_app.py +168 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_main.py +150 -4
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_main_args.py +59 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_model_config.py +25 -1
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_server.py +33 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_sessions.py +128 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_status.py +2 -2
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_thread_selector.py +298 -11
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/uv.lock +2 -2
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/.gitignore +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/DEV.md +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/Makefile +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/README.md +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/THREAT_MODEL.md +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/__init__.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/__main__.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/_ask_user_types.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/_cli_context.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/_constants.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/_debug.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/_env_vars.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/_git.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/_server_config.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/_session_stats.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/_testing_models.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/_textual_patches.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/agent.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/app.tcss +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/ask_user.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/auth_store.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/built_in_skills/__init__.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/built_in_skills/remember/SKILL.md +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/built_in_skills/skill-creator/SKILL.md +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/built_in_skills/skill-creator/scripts/init_skill.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/built_in_skills/skill-creator/scripts/quick_validate.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/clipboard.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/command_registry.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/configurable_model.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/default_agent_prompt.md +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/deploy/__init__.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/deploy/bundler.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/deploy/commands.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/deploy/config.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/deploy/context_hub.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/deploy/frontend_dist/assets/anonymous-B9UzAXQd.js +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/deploy/frontend_dist/assets/clerk-5xHgyQyG.js +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/deploy/frontend_dist/assets/highlighted-body-OFNGDK62-rX-7qT8o.js +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/deploy/frontend_dist/assets/index-DM3gptpu.js +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/deploy/frontend_dist/assets/index-Ddy7F6KI.css +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/deploy/frontend_dist/assets/supabase-S6NACDgm.js +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/deploy/frontend_dist/index.html +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/deploy/frontend_dist/logo-dark.svg +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/deploy/frontend_dist/logo-light.svg +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/deploy/templates.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/editor.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/event_bus.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/extras_info.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/file_ops.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/formatting.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/hooks.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/input.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/integrations/__init__.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/integrations/sandbox_factory.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/integrations/sandbox_provider.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/iterm_cursor_guide.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/local_context.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/mcp_auth.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/mcp_commands.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/mcp_providers/__init__.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/mcp_providers/_registry.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/mcp_providers/base.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/mcp_providers/github.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/mcp_providers/slack.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/mcp_tools.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/mcp_trust.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/media_utils.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/non_interactive.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/notifications.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/offload.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/onboarding.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/output.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/project_utils.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/py.typed +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/remote_client.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/server_manager.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/skills/__init__.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/skills/commands.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/skills/invocation.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/skills/load.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/state_migration.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/subagents.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/system_prompt.md +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/terminal_capabilities.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/textual_adapter.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/theme.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/token_state.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/tool_display.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/tools.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/unicode_security.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/update_check.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/widgets/__init__.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/widgets/_links.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/widgets/agent_selector.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/widgets/approval.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/widgets/ask_user.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/widgets/auth.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/widgets/autocomplete.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/widgets/chat_input.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/widgets/diff.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/widgets/history.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/widgets/launch_init.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/widgets/loading.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/widgets/mcp_viewer.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/widgets/message_store.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/widgets/messages.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/widgets/model_selector.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/widgets/notification_center.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/widgets/notification_detail.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/widgets/notification_settings.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/widgets/theme_selector.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/widgets/tool_renderers.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/widgets/tool_widgets.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/widgets/update_available.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/deepagents_cli/widgets/welcome.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/examples/deploy-content-writer/.env.example +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/examples/deploy-content-writer/skills/blog-post/SKILL.md +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/examples/deploy-content-writer/skills/social-media/SKILL.md +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/examples/deploy-content-writer/user/context.md +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/examples/deploy-content-writer/user/preferences.md +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/examples/skills/arxiv-search/SKILL.md +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/examples/skills/arxiv-search/arxiv_search.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/examples/skills/langgraph-docs/SKILL.md +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/examples/skills/skill-creator/SKILL.md +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/examples/skills/skill-creator/scripts/init_skill.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/examples/skills/skill-creator/scripts/quick_validate.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/examples/skills/web-research/SKILL.md +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/frontend/.nvmrc +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/frontend/index.html +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/frontend/package.json +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/frontend/postcss.config.js +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/frontend/public/logo-dark.svg +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/frontend/public/logo-light.svg +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/frontend/src/App.tsx +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/frontend/src/ThemeProvider.tsx +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/frontend/src/auth/anonymous.tsx +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/frontend/src/auth/clerk.tsx +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/frontend/src/auth/loader.tsx +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/frontend/src/auth/supabase.tsx +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/frontend/src/auth/types.ts +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/frontend/src/components/AppHeader.tsx +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/frontend/src/components/FilePanels.tsx +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/frontend/src/components/MessageList.tsx +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/frontend/src/components/SubagentActivity.tsx +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/frontend/src/components/ThreadPicker.tsx +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/frontend/src/components/TodosPanel.tsx +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/frontend/src/components/ToolCallCard.tsx +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/frontend/src/components/toolcalls/FileToolCard.tsx +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/frontend/src/components/toolcalls/SearchCard.tsx +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/frontend/src/components/toolcalls/ThinkCard.tsx +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/frontend/src/components/toolcalls/TodosCard.tsx +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/frontend/src/components/toolcalls/index.ts +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/frontend/src/constants.ts +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/frontend/src/index.css +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/frontend/src/main.tsx +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/frontend/src/runtimeConfig.ts +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/frontend/src/types.ts +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/frontend/src/vite-env.d.ts +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/frontend/tsconfig.json +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/frontend/vite.config.ts +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/images/cli.png +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/scripts/check_imports.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/scripts/debug_server.sh +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/scripts/install.sh +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/README.md +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/integration_tests/__init__.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/integration_tests/benchmarks/__init__.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/integration_tests/benchmarks/test_codspeed_import_benchmarks.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/integration_tests/benchmarks/test_startup_benchmarks.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/integration_tests/conftest.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/integration_tests/test_acp_mode.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/integration_tests/test_compact_resume.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/integration_tests/test_context_hub.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/integration_tests/test_deploy_hub.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/integration_tests/test_sandbox_factory.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/integration_tests/test_sandbox_operations.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/__init__.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/conftest.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/deploy/__init__.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/deploy/test_bundler.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/deploy/test_commands.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/deploy/test_config.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/deploy/test_context_hub.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/deploy/test_frontend_bundle.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/deploy/test_frontend_config.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/skills/__init__.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/skills/test_commands.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/skills/test_load.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/skills/test_skills_json.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_agent.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_agent_friendly.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_agent_selector.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_approval.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_args.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_ask_user.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_ask_user_middleware.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_auth_store.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_auth_widgets.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_autocomplete.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_charset.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_chat_input.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_clipboard.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_command_registry.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_compact_tool.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_config.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_configurable_model.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_debug.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_editor.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_end_to_end.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_env_vars.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_event_bus.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_exception_handling.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_extras_info.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_file_ops.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_formatting.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_git.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_history.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_hooks.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_imports.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_input_parsing.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_iterm_cursor_guide.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_launch_init.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_links.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_loading.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_local_context.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_main_acp_mode.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_mcp_auth.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_mcp_commands.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_mcp_tools.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_mcp_trust.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_mcp_viewer.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_media_utils.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_message_store.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_messages.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_model_selector.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_model_switch.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_non_interactive.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_notification_center.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_notification_detail.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_notifications.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_offload.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_offload_dict_messages.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_onboarding.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_output.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_reload.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_remote_client.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_sandbox_factory.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_server_config.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_server_graph.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_server_helpers.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_server_manager.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_session_stats.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_shell_allow_list.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_skill_invocation.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_startup_fast_paths.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_state_migration.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_subagents.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_terminal_capabilities.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_textual_adapter.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_textual_patches.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_theme.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_token_tracker.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_tool_display.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_ui.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_unicode_security.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_update_available.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_update_check.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_update_progress.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_version.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/test_welcome.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/tools/__init__.py +0 -0
- {deepagents_cli-0.0.53 → deepagents_cli-0.0.54}/tests/unit_tests/tools/test_fetch_url.py +0 -0
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Deep Agents CLI Changelog
|
|
2
2
|
|
|
3
|
+
## [0.0.54](https://github.com/langchain-ai/deepagents/compare/deepagents-cli==0.0.53...deepagents-cli==0.0.54) (2026-05-11)
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
* Allow filtering threads by directory ([#3290](https://github.com/langchain-ai/deepagents/issues/3290)) ([07a973a](https://github.com/langchain-ai/deepagents/commit/07a973ae5b0256fddfd9591dc88c7987e5581264))
|
|
8
|
+
* Show sandbox provider in header `sub_title` ([#3295](https://github.com/langchain-ai/deepagents/issues/3295)) ([779f7f4](https://github.com/langchain-ai/deepagents/commit/779f7f45c501f3c6d53e12087e3d4c340ef8aded))
|
|
9
|
+
* Surface sandbox startup errors in server crash messages ([#3306](https://github.com/langchain-ai/deepagents/issues/3306)) ([2606d57](https://github.com/langchain-ai/deepagents/commit/2606d57b623f16955df6f91e693051f4b61f6120))
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* Allow TUI launch without preconfigured model credentials ([#3301](https://github.com/langchain-ai/deepagents/issues/3301)) ([aa28ff7](https://github.com/langchain-ai/deepagents/commit/aa28ff73768a826b216bfa54d76ecd313c325077))
|
|
14
|
+
* Suppress token placeholder on first invoke ([#3302](https://github.com/langchain-ai/deepagents/issues/3302)) ([c21dee2](https://github.com/langchain-ai/deepagents/commit/c21dee2e9bc1a7d3f52ff62e9e66d1caaaf7b464))
|
|
15
|
+
* Sync thread ID and render clickable link on `/clear` ([#3305](https://github.com/langchain-ai/deepagents/issues/3305)) ([0904974](https://github.com/langchain-ai/deepagents/commit/0904974d52dff259809d00a7a8b26c3e894cc0c0))
|
|
16
|
+
|
|
3
17
|
## [0.0.53](https://github.com/langchain-ai/deepagents/compare/deepagents-cli==0.0.52...deepagents-cli==0.0.53) (2026-05-10)
|
|
4
18
|
|
|
5
19
|
### Features
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: deepagents-cli
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.54
|
|
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/
|
|
@@ -45,7 +45,7 @@ Requires-Dist: packaging>=23.0
|
|
|
45
45
|
Requires-Dist: pillow<13.0.0,>=10.0.0
|
|
46
46
|
Requires-Dist: prompt-toolkit<4.0.0,>=3.0.52
|
|
47
47
|
Requires-Dist: pyperclip<2.0.0,>=1.11.0
|
|
48
|
-
Requires-Dist: python-dotenv<2.0.0,>=1.
|
|
48
|
+
Requires-Dist: python-dotenv<2.0.0,>=1.2.2
|
|
49
49
|
Requires-Dist: pyyaml>=6.0.0
|
|
50
50
|
Requires-Dist: requests<3.0.0,>=2.0.0
|
|
51
51
|
Requires-Dist: rich<16.0.0,>=14.2.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Version information and lightweight constants for `deepagents-cli`."""
|
|
2
2
|
|
|
3
|
-
__version__ = "0.0.
|
|
3
|
+
__version__ = "0.0.54" # 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."""
|
|
@@ -92,6 +92,11 @@ from deepagents_cli.widgets.welcome import WelcomeBanner
|
|
|
92
92
|
logger = logging.getLogger(__name__)
|
|
93
93
|
_monotonic = time.monotonic
|
|
94
94
|
|
|
95
|
+
_DEFERRED_START_NOTICE = (
|
|
96
|
+
"No model is configured yet. Run `/model` to choose one. "
|
|
97
|
+
"Deep Agents will ask for credentials for the selected provider."
|
|
98
|
+
)
|
|
99
|
+
|
|
95
100
|
# Serializes process-local read-modify-write operations for `config.toml`.
|
|
96
101
|
# Without this, overlapping global-theme and per-terminal-theme saves can each
|
|
97
102
|
# read the same pre-mutation state and then clobber the other's keys.
|
|
@@ -807,6 +812,26 @@ def _build_model_switch_error_body(exc: BaseException) -> str | Content:
|
|
|
807
812
|
return f"Failed to switch model: {exc}"
|
|
808
813
|
|
|
809
814
|
|
|
815
|
+
def _build_whats_new_message(heading: str) -> Content:
|
|
816
|
+
"""Build the post-upgrade banner with a clickable changelog URL.
|
|
817
|
+
|
|
818
|
+
Args:
|
|
819
|
+
heading: First line of the post-upgrade banner.
|
|
820
|
+
|
|
821
|
+
Returns:
|
|
822
|
+
Styled banner content with the changelog URL embedded as a link.
|
|
823
|
+
"""
|
|
824
|
+
return Content.assemble(
|
|
825
|
+
(heading, TStyle(dim=True, italic=True)),
|
|
826
|
+
"\n",
|
|
827
|
+
("See what's new: ", TStyle(dim=True, italic=True)),
|
|
828
|
+
(
|
|
829
|
+
CHANGELOG_URL,
|
|
830
|
+
TStyle(dim=True, italic=True, underline=True, link=CHANGELOG_URL),
|
|
831
|
+
),
|
|
832
|
+
)
|
|
833
|
+
|
|
834
|
+
|
|
810
835
|
def _format_startup_error(error: BaseException) -> str:
|
|
811
836
|
"""Format a server-startup exception for the welcome banner.
|
|
812
837
|
|
|
@@ -863,6 +888,15 @@ _COMMAND_URLS: dict[str, str] = {
|
|
|
863
888
|
}
|
|
864
889
|
"""Slash-command to URL mapping for commands that just open a browser."""
|
|
865
890
|
|
|
891
|
+
_SANDBOX_DISPLAY_NAMES: dict[str, str] = {
|
|
892
|
+
"agentcore": "AgentCore",
|
|
893
|
+
"daytona": "Daytona",
|
|
894
|
+
"langsmith": "LangSmith",
|
|
895
|
+
"modal": "Modal",
|
|
896
|
+
"runloop": "Runloop",
|
|
897
|
+
}
|
|
898
|
+
"""Human-readable display names for sandbox providers."""
|
|
899
|
+
|
|
866
900
|
|
|
867
901
|
_toast_internals_warned: list[bool] = [False]
|
|
868
902
|
"""Single-slot flag; once `_Toast._notification` is missing, log warning once.
|
|
@@ -1034,6 +1068,7 @@ class DeepAgentsApp(App):
|
|
|
1034
1068
|
server_kwargs: dict[str, Any] | None = None,
|
|
1035
1069
|
mcp_preload_kwargs: dict[str, Any] | None = None,
|
|
1036
1070
|
model_kwargs: dict[str, Any] | None = None,
|
|
1071
|
+
defer_server_start: bool = False,
|
|
1037
1072
|
title: str | None = None,
|
|
1038
1073
|
sub_title: str | None = None,
|
|
1039
1074
|
**kwargs: Any,
|
|
@@ -1086,6 +1121,8 @@ class DeepAgentsApp(App):
|
|
|
1086
1121
|
|
|
1087
1122
|
When provided, model creation runs in a background worker after
|
|
1088
1123
|
first paint instead of blocking startup.
|
|
1124
|
+
defer_server_start: Whether to keep CLI-owned server startup paused
|
|
1125
|
+
until the user configures credentials or explicitly picks a model.
|
|
1089
1126
|
title: Override the Textual `App.title` shown in the optional
|
|
1090
1127
|
header bar.
|
|
1091
1128
|
|
|
@@ -1250,12 +1287,21 @@ class DeepAgentsApp(App):
|
|
|
1250
1287
|
"""Cached kwargs for `start_server_and_get_agent`.
|
|
1251
1288
|
|
|
1252
1289
|
When non-`None`, startup is deferred and the UI begins in
|
|
1253
|
-
"Connecting..." state.
|
|
1290
|
+
"Connecting..." state unless `_server_startup_deferred` is set.
|
|
1254
1291
|
|
|
1255
1292
|
Re-used so downstream features that restart the server (e.g. `/agents`)
|
|
1256
1293
|
start from the same config.
|
|
1257
1294
|
"""
|
|
1258
1295
|
|
|
1296
|
+
self._server_startup_deferred = defer_server_start
|
|
1297
|
+
"""True when no model can be selected yet, usually first launch with
|
|
1298
|
+
no credentials. The TUI is usable, but server startup waits for
|
|
1299
|
+
`/auth`, `/reload`, or `/model`.
|
|
1300
|
+
"""
|
|
1301
|
+
|
|
1302
|
+
self._server_startup_deferred_notice_shown = False
|
|
1303
|
+
"""Whether the first-launch no-model guidance has been mounted."""
|
|
1304
|
+
|
|
1259
1305
|
self._mcp_preload_kwargs = mcp_preload_kwargs
|
|
1260
1306
|
"""Kwargs for `_preload_session_mcp_server_info`, run concurrently
|
|
1261
1307
|
with server startup when `server_kwargs` is set."""
|
|
@@ -1278,6 +1324,12 @@ class DeepAgentsApp(App):
|
|
|
1278
1324
|
self._sandbox_type: str | None = raw if raw and raw != "none" else None
|
|
1279
1325
|
"""Normalized sandbox type (or `None`), attached to trace metadata."""
|
|
1280
1326
|
|
|
1327
|
+
if sub_title is None and self._sandbox_type is not None:
|
|
1328
|
+
display = _SANDBOX_DISPLAY_NAMES.get(
|
|
1329
|
+
self._sandbox_type, self._sandbox_type.title()
|
|
1330
|
+
)
|
|
1331
|
+
self.sub_title = f"Sandbox: {display}"
|
|
1332
|
+
|
|
1281
1333
|
# Per-turn model overrides
|
|
1282
1334
|
self._model_override: str | None = None
|
|
1283
1335
|
"""Per-turn model override set via `/model`; `None` uses session default."""
|
|
@@ -1336,7 +1388,9 @@ class DeepAgentsApp(App):
|
|
|
1336
1388
|
"""
|
|
1337
1389
|
|
|
1338
1390
|
# Lifecycle flags & re-entry guards
|
|
1339
|
-
self._connecting =
|
|
1391
|
+
self._connecting = (
|
|
1392
|
+
server_kwargs is not None and not self._server_startup_deferred
|
|
1393
|
+
)
|
|
1340
1394
|
"""True while the backing server is being started or restarted.
|
|
1341
1395
|
|
|
1342
1396
|
Gates message handling so user input is queued until the agent is
|
|
@@ -1886,6 +1940,9 @@ class DeepAgentsApp(App):
|
|
|
1886
1940
|
self._ui_adapter._on_tokens_pending = self._show_pending_tokens
|
|
1887
1941
|
self._ui_adapter._on_tokens_show = self._show_tokens
|
|
1888
1942
|
|
|
1943
|
+
if self._server_startup_deferred:
|
|
1944
|
+
await self._mount_deferred_start_notice()
|
|
1945
|
+
|
|
1889
1946
|
# Fire-and-forget workers — none of these block the event loop.
|
|
1890
1947
|
|
|
1891
1948
|
# Discover skills first so /skill: autocomplete is ready as early
|
|
@@ -1899,7 +1956,7 @@ class DeepAgentsApp(App):
|
|
|
1899
1956
|
self.run_worker(self._init_session_state, exclusive=True, group="session-init")
|
|
1900
1957
|
|
|
1901
1958
|
# Server startup (model creation + server process)
|
|
1902
|
-
if self._server_kwargs is not None:
|
|
1959
|
+
if self._server_kwargs is not None and not self._server_startup_deferred:
|
|
1903
1960
|
self.run_worker(
|
|
1904
1961
|
self._start_server_background,
|
|
1905
1962
|
exclusive=True,
|
|
@@ -1968,7 +2025,7 @@ class DeepAgentsApp(App):
|
|
|
1968
2025
|
# `on_deep_agents_app_server_ready` fires; otherwise run it now so the
|
|
1969
2026
|
# non-connecting path (pre-built agent) also honors `--startup-cmd` and
|
|
1970
2027
|
# serializes startup against user input.
|
|
1971
|
-
if not self._connecting:
|
|
2028
|
+
if not self._connecting and not self._server_startup_deferred:
|
|
1972
2029
|
self.call_after_refresh(
|
|
1973
2030
|
lambda: asyncio.create_task(self._run_session_start_sequence())
|
|
1974
2031
|
)
|
|
@@ -2820,9 +2877,7 @@ class DeepAgentsApp(App):
|
|
|
2820
2877
|
else:
|
|
2821
2878
|
heading = f"Updated to v{cli_version}"
|
|
2822
2879
|
|
|
2823
|
-
await self._mount_message(
|
|
2824
|
-
AppMessage(f"{heading}\nSee what's new: {CHANGELOG_URL}")
|
|
2825
|
-
)
|
|
2880
|
+
await self._mount_message(AppMessage(_build_whats_new_message(heading)))
|
|
2826
2881
|
except Exception:
|
|
2827
2882
|
logger.debug("What's new banner display failed", exc_info=True)
|
|
2828
2883
|
return
|
|
@@ -3720,6 +3775,9 @@ class DeepAgentsApp(App):
|
|
|
3720
3775
|
startup command before any user-facing agent work guarantees the
|
|
3721
3776
|
agent never observes input until the command has completed.
|
|
3722
3777
|
"""
|
|
3778
|
+
if self._server_startup_deferred:
|
|
3779
|
+
return
|
|
3780
|
+
|
|
3723
3781
|
if self._launch_init_requested:
|
|
3724
3782
|
self._ensure_launch_init_task()
|
|
3725
3783
|
launch_init_task = self._launch_init_task
|
|
@@ -4769,13 +4827,18 @@ class DeepAgentsApp(App):
|
|
|
4769
4827
|
# Reset thread to start fresh conversation
|
|
4770
4828
|
if self._session_state:
|
|
4771
4829
|
new_thread_id = self._session_state.reset_thread()
|
|
4830
|
+
self._lc_thread_id = new_thread_id
|
|
4772
4831
|
try:
|
|
4773
4832
|
banner = self.query_one("#welcome-banner", WelcomeBanner)
|
|
4774
4833
|
banner.update_thread_id(new_thread_id)
|
|
4775
4834
|
except NoMatches:
|
|
4776
4835
|
pass
|
|
4777
|
-
|
|
4778
|
-
|
|
4836
|
+
thread_msg_widget = AppMessage(f"Started new thread: {new_thread_id}")
|
|
4837
|
+
await self._mount_message(thread_msg_widget)
|
|
4838
|
+
self._schedule_thread_message_link(
|
|
4839
|
+
thread_msg_widget,
|
|
4840
|
+
prefix="Started new thread",
|
|
4841
|
+
thread_id=new_thread_id,
|
|
4779
4842
|
)
|
|
4780
4843
|
elif cmd == "/copy":
|
|
4781
4844
|
await self._mount_message(UserMessage(command))
|
|
@@ -5030,6 +5093,7 @@ class DeepAgentsApp(App):
|
|
|
5030
5093
|
skill_lines.append(f" - Removed: {', '.join(removed_skills)}")
|
|
5031
5094
|
report += "\nSkills updated:\n" + "\n".join(skill_lines)
|
|
5032
5095
|
await self._mount_message(AppMessage(report))
|
|
5096
|
+
await self._maybe_start_deferred_server_from_default()
|
|
5033
5097
|
elif cmd.startswith("/skill:"):
|
|
5034
5098
|
await self._handle_skill_command(command)
|
|
5035
5099
|
# -- Hidden debug commands (not in COMMANDS / autocomplete) -----------
|
|
@@ -5461,6 +5525,8 @@ class DeepAgentsApp(App):
|
|
|
5461
5525
|
self._run_agent_task(message, message_kwargs=message_kwargs),
|
|
5462
5526
|
exclusive=False,
|
|
5463
5527
|
)
|
|
5528
|
+
elif self._server_startup_deferred:
|
|
5529
|
+
await self._mount_message(AppMessage(_DEFERRED_START_NOTICE))
|
|
5464
5530
|
elif not self._server_startup_error:
|
|
5465
5531
|
# When a server-startup failure is in flight, the chat
|
|
5466
5532
|
# `ErrorMessage` mounted by `on_deep_agents_app_server_start_failed`
|
|
@@ -5469,6 +5535,13 @@ class DeepAgentsApp(App):
|
|
|
5469
5535
|
AppMessage("Agent not configured for this session.")
|
|
5470
5536
|
)
|
|
5471
5537
|
|
|
5538
|
+
async def _mount_deferred_start_notice(self) -> None:
|
|
5539
|
+
"""Tell first-launch users how to configure model credentials."""
|
|
5540
|
+
if self._server_startup_deferred_notice_shown:
|
|
5541
|
+
return
|
|
5542
|
+
self._server_startup_deferred_notice_shown = True
|
|
5543
|
+
await self._mount_message(AppMessage(_DEFERRED_START_NOTICE))
|
|
5544
|
+
|
|
5472
5545
|
async def _run_agent_task(
|
|
5473
5546
|
self,
|
|
5474
5547
|
message: str,
|
|
@@ -6991,6 +7064,8 @@ class DeepAgentsApp(App):
|
|
|
6991
7064
|
def handle_result(_result: None) -> None:
|
|
6992
7065
|
if self._chat_input:
|
|
6993
7066
|
self._chat_input.focus_input()
|
|
7067
|
+
task = asyncio.create_task(self._maybe_start_deferred_server_from_default())
|
|
7068
|
+
task.add_done_callback(_log_task_exception)
|
|
6994
7069
|
|
|
6995
7070
|
self.push_screen(AuthManagerScreen(), handle_result)
|
|
6996
7071
|
|
|
@@ -8205,14 +8280,13 @@ class DeepAgentsApp(App):
|
|
|
8205
8280
|
timeout=3,
|
|
8206
8281
|
)
|
|
8207
8282
|
return
|
|
8208
|
-
# Recover from a
|
|
8209
|
-
#
|
|
8210
|
-
#
|
|
8211
|
-
# Only valid for CLI-owned servers.
|
|
8283
|
+
# Recover from a startup that has not produced a server yet:
|
|
8284
|
+
# either a deferred first launch with no credentials, or a
|
|
8285
|
+
# failed startup such as `MissingCredentialsError`.
|
|
8212
8286
|
if (
|
|
8213
|
-
self.
|
|
8214
|
-
|
|
8215
|
-
):
|
|
8287
|
+
self._server_startup_deferred
|
|
8288
|
+
or self._server_startup_error is not None
|
|
8289
|
+
) and self._server_kwargs is not None:
|
|
8216
8290
|
await self._retry_startup_with_model(
|
|
8217
8291
|
model_spec, extra_kwargs=extra_kwargs
|
|
8218
8292
|
)
|
|
@@ -8386,6 +8460,7 @@ class DeepAgentsApp(App):
|
|
|
8386
8460
|
|
|
8387
8461
|
self._server_startup_error = None
|
|
8388
8462
|
self._server_startup_missing_credentials_provider = None
|
|
8463
|
+
self._server_startup_deferred = False
|
|
8389
8464
|
self._connecting = True
|
|
8390
8465
|
try:
|
|
8391
8466
|
banner = self.query_one("#welcome-banner", WelcomeBanner)
|
|
@@ -8415,6 +8490,32 @@ class DeepAgentsApp(App):
|
|
|
8415
8490
|
group="server-startup",
|
|
8416
8491
|
)
|
|
8417
8492
|
|
|
8493
|
+
async def _maybe_start_deferred_server_from_default(self) -> bool:
|
|
8494
|
+
"""Start a deferred first-launch server once a default model resolves.
|
|
8495
|
+
|
|
8496
|
+
Returns:
|
|
8497
|
+
`True` when startup was kicked off, otherwise `False`.
|
|
8498
|
+
"""
|
|
8499
|
+
if not self._server_startup_deferred:
|
|
8500
|
+
return False
|
|
8501
|
+
|
|
8502
|
+
from deepagents_cli.config import _get_default_model_spec
|
|
8503
|
+
from deepagents_cli.model_config import (
|
|
8504
|
+
ModelConfigError,
|
|
8505
|
+
NoCredentialsConfiguredError,
|
|
8506
|
+
)
|
|
8507
|
+
|
|
8508
|
+
try:
|
|
8509
|
+
model_spec = _get_default_model_spec()
|
|
8510
|
+
except NoCredentialsConfiguredError:
|
|
8511
|
+
return False
|
|
8512
|
+
except ModelConfigError as exc:
|
|
8513
|
+
await self._mount_message(ErrorMessage(str(exc)))
|
|
8514
|
+
return False
|
|
8515
|
+
|
|
8516
|
+
await self._retry_startup_with_model(model_spec)
|
|
8517
|
+
return True
|
|
8518
|
+
|
|
8418
8519
|
async def _set_default_model(self, model_spec: str) -> None:
|
|
8419
8520
|
"""Set the default model in config without switching the current session.
|
|
8420
8521
|
|
|
@@ -8505,6 +8606,7 @@ async def run_textual_app(
|
|
|
8505
8606
|
server_kwargs: dict[str, Any] | None = None,
|
|
8506
8607
|
mcp_preload_kwargs: dict[str, Any] | None = None,
|
|
8507
8608
|
model_kwargs: dict[str, Any] | None = None,
|
|
8609
|
+
defer_server_start: bool = False,
|
|
8508
8610
|
title: str | None = None,
|
|
8509
8611
|
sub_title: str | None = None,
|
|
8510
8612
|
) -> AppResult:
|
|
@@ -8550,6 +8652,8 @@ async def run_textual_app(
|
|
|
8550
8652
|
|
|
8551
8653
|
When provided, model creation runs in a background worker after
|
|
8552
8654
|
first paint so the splash screen appears immediately.
|
|
8655
|
+
defer_server_start: Whether to keep CLI-owned server startup paused
|
|
8656
|
+
until credentials or a model are configured from inside the TUI.
|
|
8553
8657
|
title: Override the Textual `App.title` shown in the optional header
|
|
8554
8658
|
bar (gated on `DEEPAGENTS_CLI_SHOW_HEADER`). When `None`, the
|
|
8555
8659
|
default `"Deep Agents"` is used.
|
|
@@ -8577,6 +8681,7 @@ async def run_textual_app(
|
|
|
8577
8681
|
server_kwargs=server_kwargs,
|
|
8578
8682
|
mcp_preload_kwargs=mcp_preload_kwargs,
|
|
8579
8683
|
model_kwargs=model_kwargs,
|
|
8684
|
+
defer_server_start=defer_server_start,
|
|
8580
8685
|
title=title,
|
|
8581
8686
|
sub_title=sub_title,
|
|
8582
8687
|
)
|
|
@@ -1847,12 +1847,18 @@ def _get_default_model_spec() -> str:
|
|
|
1847
1847
|
3. Auto-detection based on available API credentials.
|
|
1848
1848
|
|
|
1849
1849
|
Returns:
|
|
1850
|
-
Model specification in provider:model format.
|
|
1850
|
+
Model specification in `provider:model` format.
|
|
1851
1851
|
|
|
1852
1852
|
Raises:
|
|
1853
|
-
|
|
1853
|
+
NoCredentialsConfiguredError: If no credentials are configured for any
|
|
1854
|
+
of the auto-detectable providers. Callers may catch this to defer
|
|
1855
|
+
startup and prompt for credentials interactively.
|
|
1854
1856
|
"""
|
|
1855
|
-
from deepagents_cli.model_config import
|
|
1857
|
+
from deepagents_cli.model_config import (
|
|
1858
|
+
ModelConfig,
|
|
1859
|
+
NoCredentialsConfiguredError,
|
|
1860
|
+
get_provider_auth_status,
|
|
1861
|
+
)
|
|
1856
1862
|
|
|
1857
1863
|
config = ModelConfig.load()
|
|
1858
1864
|
if config.default_model:
|
|
@@ -1861,19 +1867,25 @@ def _get_default_model_spec() -> str:
|
|
|
1861
1867
|
if config.recent_model:
|
|
1862
1868
|
return config.recent_model
|
|
1863
1869
|
|
|
1864
|
-
|
|
1865
|
-
|
|
1870
|
+
# `is True` deliberately excludes `ProviderAuthState.UNKNOWN` (which maps
|
|
1871
|
+
# to `as_legacy_bool() -> None`). For the three explicit-credential
|
|
1872
|
+
# providers below, an UNKNOWN result means we cannot prove auth works, so
|
|
1873
|
+
# we fall through rather than pick an unverifiable default. If an
|
|
1874
|
+
# implicit-auth provider (e.g., Vertex ADC) is added to this fallback
|
|
1875
|
+
# list, switch to checking `state` against the relevant
|
|
1876
|
+
# `ProviderAuthState` members directly.
|
|
1877
|
+
if get_provider_auth_status("openai").as_legacy_bool() is True:
|
|
1866
1878
|
return "openai:gpt-5.5"
|
|
1867
|
-
if
|
|
1879
|
+
if get_provider_auth_status("anthropic").as_legacy_bool() is True:
|
|
1868
1880
|
return "anthropic:claude-opus-4-7"
|
|
1869
|
-
if
|
|
1881
|
+
if get_provider_auth_status("google_genai").as_legacy_bool() is True:
|
|
1870
1882
|
return "google_genai:gemini-3.1-pro-preview"
|
|
1871
1883
|
|
|
1872
1884
|
msg = (
|
|
1873
1885
|
"No credentials configured. Please set one of: "
|
|
1874
1886
|
"ANTHROPIC_API_KEY, OPENAI_API_KEY, or GOOGLE_API_KEY"
|
|
1875
1887
|
)
|
|
1876
|
-
raise
|
|
1888
|
+
raise NoCredentialsConfiguredError(msg)
|
|
1877
1889
|
|
|
1878
1890
|
|
|
1879
1891
|
_OPENROUTER_APP_URL = "https://pypi.org/project/deepagents-cli/"
|
|
@@ -81,6 +81,38 @@ def _resolve_agent_arg(args: argparse.Namespace) -> str:
|
|
|
81
81
|
return DEFAULT_AGENT_NAME
|
|
82
82
|
|
|
83
83
|
|
|
84
|
+
def _normalize_cwd_filter(cwd: str | None) -> str | None:
|
|
85
|
+
"""Normalize the `threads list --cwd` filter for metadata matching.
|
|
86
|
+
|
|
87
|
+
Storage uses `str(Path.cwd())` (absolute, no symlink resolution — see
|
|
88
|
+
`build_run_metadata`). We mirror that here with lexical normalization
|
|
89
|
+
rather than `.resolve()` so a user invoking from a symlinked path doesn't
|
|
90
|
+
get an empty result set due to symlink normalization.
|
|
91
|
+
|
|
92
|
+
Args:
|
|
93
|
+
cwd: Parsed `--cwd` value. An empty string means the flag was passed
|
|
94
|
+
without a value and should use the current working directory.
|
|
95
|
+
|
|
96
|
+
Returns:
|
|
97
|
+
Absolute path string for filtering, or `None` when no filter was
|
|
98
|
+
requested. Returns `None` if the current working directory cannot
|
|
99
|
+
be determined (bare `--cwd` only).
|
|
100
|
+
"""
|
|
101
|
+
if cwd is None:
|
|
102
|
+
return None
|
|
103
|
+
if cwd == "": # noqa: PLC1901
|
|
104
|
+
try:
|
|
105
|
+
return str(Path.cwd())
|
|
106
|
+
except OSError:
|
|
107
|
+
logger.warning(
|
|
108
|
+
"Could not determine working directory for --cwd; "
|
|
109
|
+
"no cwd filter will be applied",
|
|
110
|
+
exc_info=True,
|
|
111
|
+
)
|
|
112
|
+
return None
|
|
113
|
+
return os.path.normpath(str(Path(cwd).expanduser().absolute()))
|
|
114
|
+
|
|
115
|
+
|
|
84
116
|
def _recent_agent_is_valid(name: str) -> bool:
|
|
85
117
|
"""Return `True` when `~/.deepagents/<name>/` still exists on disk.
|
|
86
118
|
|
|
@@ -627,6 +659,16 @@ def parse_args() -> argparse.Namespace:
|
|
|
627
659
|
default=None,
|
|
628
660
|
help="Filter by git branch name",
|
|
629
661
|
)
|
|
662
|
+
threads_list.add_argument(
|
|
663
|
+
"--cwd",
|
|
664
|
+
nargs="?",
|
|
665
|
+
const="",
|
|
666
|
+
default=None,
|
|
667
|
+
help=(
|
|
668
|
+
"Filter by working directory. With no value, uses the current "
|
|
669
|
+
"directory; pass a path to filter by that directory instead."
|
|
670
|
+
),
|
|
671
|
+
)
|
|
630
672
|
threads_list.add_argument(
|
|
631
673
|
"-v",
|
|
632
674
|
"--verbose",
|
|
@@ -994,15 +1036,23 @@ async def run_textual_cli_async(
|
|
|
994
1036
|
detect_provider,
|
|
995
1037
|
settings,
|
|
996
1038
|
)
|
|
997
|
-
from deepagents_cli.model_config import
|
|
1039
|
+
from deepagents_cli.model_config import (
|
|
1040
|
+
ModelConfigError,
|
|
1041
|
+
ModelSpec,
|
|
1042
|
+
NoCredentialsConfiguredError,
|
|
1043
|
+
)
|
|
998
1044
|
from deepagents_cli.onboarding import should_run_onboarding
|
|
999
1045
|
|
|
1000
1046
|
# Resolve display-name cheaply (<1ms, no langchain) so the status
|
|
1001
1047
|
# bar can show the model on first paint. The expensive create_model()
|
|
1002
1048
|
# (~560ms) is deferred to a background worker.
|
|
1003
1049
|
|
|
1050
|
+
defer_server_start = False
|
|
1004
1051
|
try:
|
|
1005
1052
|
resolved_spec = model_name or _get_default_model_spec()
|
|
1053
|
+
except NoCredentialsConfiguredError:
|
|
1054
|
+
resolved_spec = ""
|
|
1055
|
+
defer_server_start = True
|
|
1006
1056
|
except ModelConfigError as e:
|
|
1007
1057
|
from rich.markup import escape
|
|
1008
1058
|
|
|
@@ -1011,19 +1061,25 @@ async def run_textual_cli_async(
|
|
|
1011
1061
|
console.print(f"[bold red]Error:[/bold red] {escape(str(e))}", highlight=False)
|
|
1012
1062
|
return AppResult(return_code=1, thread_id=None)
|
|
1013
1063
|
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1064
|
+
if resolved_spec:
|
|
1065
|
+
parsed = ModelSpec.try_parse(resolved_spec)
|
|
1066
|
+
if parsed:
|
|
1067
|
+
settings.model_provider = parsed.provider
|
|
1068
|
+
settings.model_name = parsed.model
|
|
1069
|
+
else:
|
|
1070
|
+
settings.model_name = resolved_spec
|
|
1071
|
+
settings.model_provider = detect_provider(resolved_spec) or ""
|
|
1018
1072
|
else:
|
|
1019
|
-
settings.
|
|
1020
|
-
settings.
|
|
1021
|
-
|
|
1022
|
-
model_kwargs: dict[str, Any] =
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1073
|
+
settings.model_provider = ""
|
|
1074
|
+
settings.model_name = ""
|
|
1075
|
+
|
|
1076
|
+
model_kwargs: dict[str, Any] | None = None
|
|
1077
|
+
if not defer_server_start:
|
|
1078
|
+
model_kwargs = {
|
|
1079
|
+
"model_spec": model_name or resolved_spec,
|
|
1080
|
+
"extra_kwargs": model_params,
|
|
1081
|
+
"profile_overrides": profile_override,
|
|
1082
|
+
}
|
|
1027
1083
|
|
|
1028
1084
|
# Build kwargs for deferred server startup (runs inside the TUI).
|
|
1029
1085
|
# Never pass auto_approve to the server — the interactive server must
|
|
@@ -1032,7 +1088,7 @@ async def run_textual_cli_async(
|
|
|
1032
1088
|
# session_state.auto_approve in textual_adapter.py.
|
|
1033
1089
|
server_kwargs: dict[str, Any] = {
|
|
1034
1090
|
"assistant_id": assistant_id,
|
|
1035
|
-
"model_name": model_name,
|
|
1091
|
+
"model_name": model_name or resolved_spec or None,
|
|
1036
1092
|
"model_params": model_params,
|
|
1037
1093
|
"sandbox_type": sandbox_type,
|
|
1038
1094
|
"sandbox_id": sandbox_id,
|
|
@@ -1068,6 +1124,7 @@ async def run_textual_cli_async(
|
|
|
1068
1124
|
server_kwargs=server_kwargs,
|
|
1069
1125
|
mcp_preload_kwargs=mcp_preload_kwargs,
|
|
1070
1126
|
model_kwargs=model_kwargs,
|
|
1127
|
+
defer_server_start=defer_server_start,
|
|
1071
1128
|
)
|
|
1072
1129
|
except Exception as e:
|
|
1073
1130
|
logger.debug("App error", exc_info=True)
|
|
@@ -1913,12 +1970,31 @@ def cli_main() -> None:
|
|
|
1913
1970
|
# "ls" is an argparse alias for "list" — argparse stores the
|
|
1914
1971
|
# alias as-is in the namespace, so we must match both values.
|
|
1915
1972
|
if args.threads_command in {"list", "ls"}:
|
|
1973
|
+
raw_cwd = getattr(args, "cwd", None)
|
|
1974
|
+
cwd_filter = _normalize_cwd_filter(raw_cwd)
|
|
1975
|
+
# Warn (but still query) when the user passed an explicit
|
|
1976
|
+
# `--cwd <path>` that does not exist on disk — otherwise a
|
|
1977
|
+
# typo would silently return "No threads found" with no hint.
|
|
1978
|
+
# Skip the check for the bare-flag (empty string) form, where
|
|
1979
|
+
# the path was generated from `Path.cwd()` and is known to
|
|
1980
|
+
# exist.
|
|
1981
|
+
if (
|
|
1982
|
+
raw_cwd not in {None, ""}
|
|
1983
|
+
and cwd_filter is not None
|
|
1984
|
+
and not Path(cwd_filter).exists()
|
|
1985
|
+
):
|
|
1986
|
+
print( # noqa: T201
|
|
1987
|
+
f"Warning: --cwd path {cwd_filter!r} does not exist; "
|
|
1988
|
+
"filtering by stored metadata anyway.",
|
|
1989
|
+
file=sys.stderr,
|
|
1990
|
+
)
|
|
1916
1991
|
asyncio.run(
|
|
1917
1992
|
list_threads_command(
|
|
1918
1993
|
agent_name=getattr(args, "agent", None),
|
|
1919
1994
|
limit=getattr(args, "limit", None),
|
|
1920
1995
|
sort_by=getattr(args, "sort", None),
|
|
1921
1996
|
branch=getattr(args, "branch", None),
|
|
1997
|
+
cwd=cwd_filter,
|
|
1922
1998
|
verbose=getattr(args, "verbose", False),
|
|
1923
1999
|
relative=getattr(args, "relative", None),
|
|
1924
2000
|
output_format=output_format,
|
|
@@ -107,6 +107,18 @@ class ModelConfigError(Exception):
|
|
|
107
107
|
"""Raised when model configuration or creation fails."""
|
|
108
108
|
|
|
109
109
|
|
|
110
|
+
class NoCredentialsConfiguredError(ModelConfigError):
|
|
111
|
+
"""Raised when no credentials are configured for any default-resolvable provider.
|
|
112
|
+
|
|
113
|
+
Distinct from `MissingCredentialsError` (which targets a specific provider
|
|
114
|
+
the user has selected): this fires from `_get_default_model_spec()` when
|
|
115
|
+
auto-detection finds no usable credentials at all. Callers (the deferred-
|
|
116
|
+
start path in the TUI and CLI) `isinstance`-check this type to recover by
|
|
117
|
+
launching the TUI with model creation deferred, rather than string-matching
|
|
118
|
+
the formatted message.
|
|
119
|
+
"""
|
|
120
|
+
|
|
121
|
+
|
|
110
122
|
class UnknownProviderError(ModelConfigError):
|
|
111
123
|
"""Raised when neither the CLI nor `init_chat_model` can infer a provider.
|
|
112
124
|
|
|
@@ -34,6 +34,8 @@ _LOG_TAIL_CHARS = 3000
|
|
|
34
34
|
"""Max chars of subprocess log appended to the early-exit `RuntimeError`
|
|
35
35
|
message. Enough to carry a Python traceback without flooding the TUI banner
|
|
36
36
|
when it surfaces via `ServerStartFailed`."""
|
|
37
|
+
_STARTUP_ERROR_MARKER = "DEEPAGENTS_STARTUP_ERROR:"
|
|
38
|
+
"""Machine-readable prefix emitted by the server subprocess for known startup errors."""
|
|
37
39
|
|
|
38
40
|
|
|
39
41
|
def _port_in_use(host: str, port: int) -> bool:
|
|
@@ -86,6 +88,22 @@ def get_server_url(host: str = _DEFAULT_HOST, port: int = _DEFAULT_PORT) -> str:
|
|
|
86
88
|
return f"http://{host}:{port}"
|
|
87
89
|
|
|
88
90
|
|
|
91
|
+
def _extract_startup_error_marker(output: str) -> str | None:
|
|
92
|
+
"""Extract a marked startup error from subprocess output.
|
|
93
|
+
|
|
94
|
+
Args:
|
|
95
|
+
output: Combined stdout/stderr captured from the server subprocess.
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
The marked startup error message, or `None` if no marker was emitted.
|
|
99
|
+
"""
|
|
100
|
+
for line in reversed(output.splitlines()):
|
|
101
|
+
if _STARTUP_ERROR_MARKER in line:
|
|
102
|
+
_, summary = line.rsplit(_STARTUP_ERROR_MARKER, 1)
|
|
103
|
+
return summary.strip() or None
|
|
104
|
+
return None
|
|
105
|
+
|
|
106
|
+
|
|
89
107
|
def generate_langgraph_json(
|
|
90
108
|
output_dir: str | Path,
|
|
91
109
|
*,
|
|
@@ -204,6 +222,9 @@ async def wait_for_server_healthy(
|
|
|
204
222
|
output = read_log() if read_log else ""
|
|
205
223
|
msg = f"Server process exited with code {process.returncode}"
|
|
206
224
|
if output:
|
|
225
|
+
summary = _extract_startup_error_marker(output)
|
|
226
|
+
if summary:
|
|
227
|
+
msg += f": {summary}"
|
|
207
228
|
msg += f"\n{output[-_LOG_TAIL_CHARS:]}"
|
|
208
229
|
raise RuntimeError(msg)
|
|
209
230
|
|