deepagents-cli 0.0.42__tar.gz → 0.0.43__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.42 → deepagents_cli-0.0.43}/.gitignore +6 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/CHANGELOG.md +7 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/PKG-INFO +1 -1
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/_version.py +1 -1
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/deploy/bundler.py +135 -9
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/deploy/commands.py +45 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/deploy/config.py +116 -7
- deepagents_cli-0.0.43/deepagents_cli/deploy/frontend_dist/assets/anonymous-B9UzAXQd.js +1 -0
- deepagents_cli-0.0.43/deepagents_cli/deploy/frontend_dist/assets/clerk-5xHgyQyG.js +23 -0
- deepagents_cli-0.0.43/deepagents_cli/deploy/frontend_dist/assets/highlighted-body-OFNGDK62-rX-7qT8o.js +1 -0
- deepagents_cli-0.0.43/deepagents_cli/deploy/frontend_dist/assets/index-DM3gptpu.js +205 -0
- deepagents_cli-0.0.43/deepagents_cli/deploy/frontend_dist/assets/index-Ddy7F6KI.css +1 -0
- deepagents_cli-0.0.43/deepagents_cli/deploy/frontend_dist/assets/supabase-S6NACDgm.js +44 -0
- deepagents_cli-0.0.43/deepagents_cli/deploy/frontend_dist/index.html +16 -0
- deepagents_cli-0.0.43/deepagents_cli/deploy/frontend_dist/logo-dark.svg +12 -0
- deepagents_cli-0.0.43/deepagents_cli/deploy/frontend_dist/logo-light.svg +12 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/deploy/templates.py +112 -0
- deepagents_cli-0.0.43/frontend/.nvmrc +1 -0
- deepagents_cli-0.0.43/frontend/index.html +15 -0
- deepagents_cli-0.0.43/frontend/package-lock.json +6207 -0
- deepagents_cli-0.0.43/frontend/package.json +34 -0
- deepagents_cli-0.0.43/frontend/postcss.config.js +5 -0
- deepagents_cli-0.0.43/frontend/public/logo-dark.svg +12 -0
- deepagents_cli-0.0.43/frontend/public/logo-light.svg +12 -0
- deepagents_cli-0.0.43/frontend/src/App.tsx +342 -0
- deepagents_cli-0.0.43/frontend/src/ThemeProvider.tsx +66 -0
- deepagents_cli-0.0.43/frontend/src/auth/anonymous.tsx +45 -0
- deepagents_cli-0.0.43/frontend/src/auth/clerk.tsx +138 -0
- deepagents_cli-0.0.43/frontend/src/auth/loader.tsx +26 -0
- deepagents_cli-0.0.43/frontend/src/auth/supabase.tsx +236 -0
- deepagents_cli-0.0.43/frontend/src/auth/types.ts +22 -0
- deepagents_cli-0.0.43/frontend/src/components/AppHeader.tsx +70 -0
- deepagents_cli-0.0.43/frontend/src/components/FilePanels.tsx +148 -0
- deepagents_cli-0.0.43/frontend/src/components/MessageList.tsx +177 -0
- deepagents_cli-0.0.43/frontend/src/components/SubagentActivity.tsx +262 -0
- deepagents_cli-0.0.43/frontend/src/components/ThreadPicker.tsx +162 -0
- deepagents_cli-0.0.43/frontend/src/components/TodosPanel.tsx +54 -0
- deepagents_cli-0.0.43/frontend/src/components/ToolCallCard.tsx +136 -0
- deepagents_cli-0.0.43/frontend/src/components/toolcalls/FileToolCard.tsx +126 -0
- deepagents_cli-0.0.43/frontend/src/components/toolcalls/SearchCard.tsx +107 -0
- deepagents_cli-0.0.43/frontend/src/components/toolcalls/ThinkCard.tsx +60 -0
- deepagents_cli-0.0.43/frontend/src/components/toolcalls/TodosCard.tsx +63 -0
- deepagents_cli-0.0.43/frontend/src/components/toolcalls/index.ts +51 -0
- deepagents_cli-0.0.43/frontend/src/constants.ts +15 -0
- deepagents_cli-0.0.43/frontend/src/index.css +220 -0
- deepagents_cli-0.0.43/frontend/src/main.tsx +20 -0
- deepagents_cli-0.0.43/frontend/src/runtimeConfig.ts +75 -0
- deepagents_cli-0.0.43/frontend/src/types.ts +22 -0
- deepagents_cli-0.0.43/frontend/src/vite-env.d.ts +1 -0
- deepagents_cli-0.0.43/frontend/tsconfig.json +19 -0
- deepagents_cli-0.0.43/frontend/vite.config.ts +25 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/pyproject.toml +7 -1
- deepagents_cli-0.0.43/tests/unit_tests/deploy/test_frontend_bundle.py +427 -0
- deepagents_cli-0.0.43/tests/unit_tests/deploy/test_frontend_config.py +181 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/uv.lock +1 -1
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/DEV.md +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/Makefile +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/README.md +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/THREAT_MODEL.md +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/__init__.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/__main__.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/_ask_user_types.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/_cli_context.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/_debug.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/_env_vars.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/_git.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/_server_config.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/_session_stats.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/_testing_models.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/_textual_patches.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/agent.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/app.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/app.tcss +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/ask_user.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/built_in_skills/__init__.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/built_in_skills/remember/SKILL.md +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/built_in_skills/skill-creator/SKILL.md +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/built_in_skills/skill-creator/scripts/init_skill.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/built_in_skills/skill-creator/scripts/quick_validate.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/clipboard.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/command_registry.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/config.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/configurable_model.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/default_agent_prompt.md +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/deploy/__init__.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/editor.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/extras_info.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/file_ops.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/formatting.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/hooks.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/input.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/integrations/__init__.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/integrations/sandbox_factory.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/integrations/sandbox_provider.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/local_context.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/main.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/mcp_tools.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/mcp_trust.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/media_utils.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/model_config.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/non_interactive.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/notifications.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/offload.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/output.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/project_utils.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/py.typed +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/remote_client.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/server.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/server_graph.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/server_manager.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/sessions.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/skills/__init__.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/skills/commands.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/skills/invocation.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/skills/load.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/subagents.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/system_prompt.md +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/terminal_capabilities.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/textual_adapter.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/theme.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/token_state.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/tool_display.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/tools.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/ui.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/unicode_security.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/update_check.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/widgets/__init__.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/widgets/_links.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/widgets/agent_selector.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/widgets/approval.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/widgets/ask_user.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/widgets/autocomplete.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/widgets/chat_input.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/widgets/diff.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/widgets/history.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/widgets/loading.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/widgets/mcp_viewer.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/widgets/message_store.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/widgets/messages.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/widgets/model_selector.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/widgets/notification_center.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/widgets/notification_detail.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/widgets/notification_settings.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/widgets/status.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/widgets/theme_selector.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/widgets/thread_selector.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/widgets/tool_renderers.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/widgets/tool_widgets.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/widgets/update_available.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/deepagents_cli/widgets/welcome.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/examples/deploy-content-writer/.env.example +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/examples/deploy-content-writer/skills/blog-post/SKILL.md +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/examples/deploy-content-writer/skills/social-media/SKILL.md +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/examples/deploy-content-writer/user/context.md +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/examples/deploy-content-writer/user/preferences.md +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/examples/skills/arxiv-search/SKILL.md +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/examples/skills/arxiv-search/arxiv_search.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/examples/skills/langgraph-docs/SKILL.md +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/examples/skills/skill-creator/SKILL.md +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/examples/skills/skill-creator/scripts/init_skill.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/examples/skills/skill-creator/scripts/quick_validate.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/examples/skills/web-research/SKILL.md +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/images/cli.png +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/scripts/check_imports.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/scripts/debug_server.sh +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/scripts/install.sh +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/README.md +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/integration_tests/__init__.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/integration_tests/benchmarks/__init__.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/integration_tests/benchmarks/test_codspeed_import_benchmarks.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/integration_tests/benchmarks/test_startup_benchmarks.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/integration_tests/conftest.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/integration_tests/test_acp_mode.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/integration_tests/test_compact_resume.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/integration_tests/test_sandbox_factory.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/integration_tests/test_sandbox_operations.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/__init__.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/conftest.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/deploy/__init__.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/deploy/test_bundler.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/deploy/test_commands.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/deploy/test_config.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/skills/__init__.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/skills/test_commands.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/skills/test_load.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/skills/test_skills_json.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_agent.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_agent_friendly.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_agent_selector.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_app.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_approval.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_args.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_ask_user.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_ask_user_middleware.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_autocomplete.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_charset.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_chat_input.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_command_registry.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_compact_tool.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_config.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_configurable_model.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_debug.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_editor.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_end_to_end.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_env_vars.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_exception_handling.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_extras_info.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_file_ops.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_formatting.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_git.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_history.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_hooks.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_imports.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_input_parsing.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_links.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_loading.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_local_context.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_main.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_main_acp_mode.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_main_args.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_mcp_tools.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_mcp_trust.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_mcp_viewer.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_media_utils.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_message_store.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_messages.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_model_config.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_model_selector.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_model_switch.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_non_interactive.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_notification_center.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_notification_detail.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_notifications.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_offload.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_offload_dict_messages.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_output.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_reload.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_remote_client.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_sandbox_factory.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_server.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_server_config.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_server_graph.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_server_helpers.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_server_manager.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_session_stats.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_sessions.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_shell_allow_list.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_skill_invocation.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_status.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_subagents.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_terminal_capabilities.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_textual_adapter.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_textual_patches.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_theme.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_thread_selector.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_token_tracker.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_tool_display.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_ui.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_unicode_security.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_update_available.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_update_check.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_version.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/test_welcome.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/tools/__init__.py +0 -0
- {deepagents_cli-0.0.42 → deepagents_cli-0.0.43}/tests/unit_tests/tools/test_fetch_url.py +0 -0
|
@@ -15,6 +15,7 @@ downloads/
|
|
|
15
15
|
eggs/
|
|
16
16
|
.eggs/
|
|
17
17
|
lib/
|
|
18
|
+
!libs/cli/frontend/src/lib/
|
|
18
19
|
lib64/
|
|
19
20
|
parts/
|
|
20
21
|
sdist/
|
|
@@ -227,3 +228,8 @@ libs/cli/TEXTUAL_PROGRESS.md
|
|
|
227
228
|
|
|
228
229
|
CLAUDE.md
|
|
229
230
|
.worktrees/
|
|
231
|
+
|
|
232
|
+
# Frontend build artifacts (source tree; package data under libs/cli/deepagents_cli/deploy/frontend_dist/ is tracked)
|
|
233
|
+
libs/cli/frontend/node_modules/
|
|
234
|
+
libs/cli/frontend/dist/
|
|
235
|
+
node_modules/
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.0.43](https://github.com/langchain-ai/deepagents/compare/deepagents-cli==0.0.42...deepagents-cli==0.0.43) (2026-04-29)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **cli:** bundled chat frontend for deepagent deploy ([#2940](https://github.com/langchain-ai/deepagents/issues/2940)) ([9bde0c7](https://github.com/langchain-ai/deepagents/commit/9bde0c7835ded20e80466d8361f40784141d68d8))
|
|
9
|
+
|
|
3
10
|
## [0.0.42](https://github.com/langchain-ai/deepagents/compare/deepagents-cli==0.0.41...deepagents-cli==0.0.42) (2026-04-29)
|
|
4
11
|
|
|
5
12
|
### Features
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: deepagents-cli
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.43
|
|
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/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Version information and lightweight constants for `deepagents-cli`."""
|
|
2
2
|
|
|
3
|
-
__version__ = "0.0.
|
|
3
|
+
__version__ = "0.0.43" # 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."""
|
|
@@ -25,6 +25,8 @@ from __future__ import annotations
|
|
|
25
25
|
|
|
26
26
|
import json
|
|
27
27
|
import logging
|
|
28
|
+
import os
|
|
29
|
+
import re
|
|
28
30
|
import shutil
|
|
29
31
|
from pathlib import Path
|
|
30
32
|
from typing import Any
|
|
@@ -39,6 +41,7 @@ from deepagents_cli.deploy.config import (
|
|
|
39
41
|
load_subagents,
|
|
40
42
|
)
|
|
41
43
|
from deepagents_cli.deploy.templates import (
|
|
44
|
+
APP_PY_TEMPLATE,
|
|
42
45
|
AUTH_BLOCKS,
|
|
43
46
|
AUTH_ON_HANDLER,
|
|
44
47
|
DEPLOY_GRAPH_TEMPLATE,
|
|
@@ -69,6 +72,97 @@ _MODEL_PROVIDER_DEPS: dict[str, str] = {
|
|
|
69
72
|
}
|
|
70
73
|
"""Dependencies inferred from a provider: prefix on the model string."""
|
|
71
74
|
|
|
75
|
+
_FRONTEND_DIST_SRC = Path(__file__).parent / "frontend_dist"
|
|
76
|
+
"""Location of the shipped pre-built frontend, inside this Python package."""
|
|
77
|
+
|
|
78
|
+
_FRONTEND_PLACEHOLDER_RE = re.compile(
|
|
79
|
+
r"window\.__DEEPAGENTS_CONFIG__\s*=\s*\{[^<]*?\};",
|
|
80
|
+
re.DOTALL,
|
|
81
|
+
)
|
|
82
|
+
"""Matches the placeholder script we injected into index.html at build time."""
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _build_runtime_config_json(config: DeployConfig) -> str:
|
|
86
|
+
"""Build the JSON value injected into `window.__DEEPAGENTS_CONFIG__`.
|
|
87
|
+
|
|
88
|
+
Only reached when `[frontend].enabled` and `[auth]` is set —
|
|
89
|
+
validation guarantees both. The `is None` guards below exist so
|
|
90
|
+
the optional fields narrow for type-checkers.
|
|
91
|
+
"""
|
|
92
|
+
if config.frontend is None:
|
|
93
|
+
msg = "runtime config requires [frontend] to be configured"
|
|
94
|
+
raise ValueError(msg)
|
|
95
|
+
if config.auth is None:
|
|
96
|
+
msg = "runtime config requires [auth] to be configured"
|
|
97
|
+
raise ValueError(msg)
|
|
98
|
+
|
|
99
|
+
app_name = config.frontend.app_name or config.agent.name
|
|
100
|
+
payload: dict[str, Any] = {
|
|
101
|
+
"appName": app_name,
|
|
102
|
+
"assistantId": "agent",
|
|
103
|
+
}
|
|
104
|
+
# Optional UI-customization fields — only injected when the user
|
|
105
|
+
# set them, so the default-bundle case stays small.
|
|
106
|
+
if config.frontend.subtitle is not None:
|
|
107
|
+
payload["subtitle"] = config.frontend.subtitle
|
|
108
|
+
if config.frontend.prompts is not None:
|
|
109
|
+
payload["prompts"] = list(config.frontend.prompts)
|
|
110
|
+
|
|
111
|
+
provider = config.auth.provider
|
|
112
|
+
payload["auth"] = provider
|
|
113
|
+
if provider == "supabase":
|
|
114
|
+
payload["supabaseUrl"] = os.environ["SUPABASE_URL"]
|
|
115
|
+
payload["supabaseAnonKey"] = os.environ["SUPABASE_PUBLISHABLE_DEFAULT_KEY"]
|
|
116
|
+
elif provider == "clerk":
|
|
117
|
+
payload["clerkPublishableKey"] = os.environ["CLERK_PUBLISHABLE_KEY"]
|
|
118
|
+
elif provider == "anonymous":
|
|
119
|
+
# No env vars; payload["auth"] = "anonymous" is enough.
|
|
120
|
+
pass
|
|
121
|
+
else:
|
|
122
|
+
msg = f"Unknown auth provider for frontend: {provider}"
|
|
123
|
+
raise ValueError(msg)
|
|
124
|
+
|
|
125
|
+
# Escape `<` so a hostile or accidental `</script>` inside a string value
|
|
126
|
+
# can't break out of the inline <script> tag.
|
|
127
|
+
return json.dumps(payload, separators=(",", ":")).replace("<", "\\u003c")
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def _copy_frontend_dist(config: DeployConfig, build_dir: Path) -> None:
|
|
131
|
+
"""Copy the pre-built bundle into build_dir and rewrite the config placeholder."""
|
|
132
|
+
if not _FRONTEND_DIST_SRC.is_dir():
|
|
133
|
+
msg = (
|
|
134
|
+
f"Shipped frontend bundle not found at {_FRONTEND_DIST_SRC}. "
|
|
135
|
+
"Did you run `make build-frontends`?"
|
|
136
|
+
)
|
|
137
|
+
raise RuntimeError(msg)
|
|
138
|
+
|
|
139
|
+
dest = build_dir / "frontend_dist"
|
|
140
|
+
if dest.exists():
|
|
141
|
+
shutil.rmtree(dest)
|
|
142
|
+
shutil.copytree(_FRONTEND_DIST_SRC, dest)
|
|
143
|
+
|
|
144
|
+
index_html = dest / "index.html"
|
|
145
|
+
if not index_html.is_file():
|
|
146
|
+
msg = f"expected index.html inside {_FRONTEND_DIST_SRC}"
|
|
147
|
+
raise RuntimeError(msg)
|
|
148
|
+
|
|
149
|
+
html = index_html.read_text(encoding="utf-8")
|
|
150
|
+
payload = _build_runtime_config_json(config)
|
|
151
|
+
replacement = f"window.__DEEPAGENTS_CONFIG__ = {payload};"
|
|
152
|
+
new_html, count = _FRONTEND_PLACEHOLDER_RE.subn(
|
|
153
|
+
lambda _m: replacement,
|
|
154
|
+
html,
|
|
155
|
+
count=1,
|
|
156
|
+
)
|
|
157
|
+
if count == 0:
|
|
158
|
+
msg = (
|
|
159
|
+
"Could not find window.__DEEPAGENTS_CONFIG__ placeholder in the "
|
|
160
|
+
"shipped index.html. The frontend bundle is out of sync with the "
|
|
161
|
+
"bundler — rebuild with `make build-frontends`."
|
|
162
|
+
)
|
|
163
|
+
raise RuntimeError(msg)
|
|
164
|
+
index_html.write_text(new_html, encoding="utf-8")
|
|
165
|
+
|
|
72
166
|
|
|
73
167
|
def bundle(
|
|
74
168
|
config: DeployConfig,
|
|
@@ -127,18 +221,38 @@ def bundle(
|
|
|
127
221
|
)
|
|
128
222
|
logger.info("Generated deploy_graph.py")
|
|
129
223
|
|
|
130
|
-
# 6. Generate auth.py
|
|
131
|
-
|
|
132
|
-
|
|
224
|
+
# 6. Generate auth.py from the [auth] provider, if any. Skipped
|
|
225
|
+
# entirely when [auth] is omitted — in that case LangSmith Cloud's
|
|
226
|
+
# default x-api-key auth applies. Validation guarantees [auth] is
|
|
227
|
+
# set whenever [frontend].enabled, so auth.py is always present
|
|
228
|
+
# for frontend deploys (including the "anonymous" provider, whose
|
|
229
|
+
# permissive handler lets the bundled UI reach /threads).
|
|
230
|
+
frontend_enabled = config.frontend is not None and config.frontend.enabled
|
|
231
|
+
auth_provider: str | None = (
|
|
232
|
+
config.auth.provider if config.auth is not None else None
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
auth_present = auth_provider is not None
|
|
236
|
+
if auth_provider is not None:
|
|
133
237
|
(build_dir / "auth.py").write_text(
|
|
134
|
-
_render_auth_py(
|
|
238
|
+
_render_auth_py(auth_provider),
|
|
135
239
|
encoding="utf-8",
|
|
136
240
|
)
|
|
137
|
-
logger.info("Generated auth.py (%s)",
|
|
241
|
+
logger.info("Generated auth.py (%s)", auth_provider)
|
|
242
|
+
|
|
243
|
+
# 6b. Copy frontend bundle when enabled.
|
|
244
|
+
if frontend_enabled:
|
|
245
|
+
_copy_frontend_dist(config, build_dir)
|
|
246
|
+
(build_dir / "app.py").write_text(APP_PY_TEMPLATE, encoding="utf-8")
|
|
247
|
+
logger.info("Copied frontend bundle and wrote app.py (%s)", auth_provider)
|
|
138
248
|
|
|
139
249
|
# 7. Render langgraph.json.
|
|
140
250
|
(build_dir / "langgraph.json").write_text(
|
|
141
|
-
_render_langgraph_json(
|
|
251
|
+
_render_langgraph_json(
|
|
252
|
+
env_present=env_present,
|
|
253
|
+
auth_present=auth_present,
|
|
254
|
+
frontend_present=frontend_enabled,
|
|
255
|
+
),
|
|
142
256
|
encoding="utf-8",
|
|
143
257
|
)
|
|
144
258
|
|
|
@@ -312,8 +426,13 @@ def _render_auth_py(provider: str) -> str:
|
|
|
312
426
|
return auth_block + AUTH_ON_HANDLER
|
|
313
427
|
|
|
314
428
|
|
|
315
|
-
def _render_langgraph_json(
|
|
316
|
-
|
|
429
|
+
def _render_langgraph_json(
|
|
430
|
+
*,
|
|
431
|
+
env_present: bool,
|
|
432
|
+
auth_present: bool = False,
|
|
433
|
+
frontend_present: bool = False,
|
|
434
|
+
) -> str:
|
|
435
|
+
"""Render `langgraph.json` — adds `"env"`, `"auth"`, `"http"` when applicable."""
|
|
317
436
|
data: dict = {
|
|
318
437
|
"dependencies": ["."],
|
|
319
438
|
"graphs": {"agent": "./deploy_graph.py:make_graph"},
|
|
@@ -323,6 +442,8 @@ def _render_langgraph_json(*, env_present: bool, auth_present: bool = False) ->
|
|
|
323
442
|
data["env"] = ".env"
|
|
324
443
|
if auth_present:
|
|
325
444
|
data["auth"] = {"path": "./auth.py:auth"}
|
|
445
|
+
if frontend_present:
|
|
446
|
+
data["http"] = {"app": "./app.py:app"}
|
|
326
447
|
return json.dumps(data, indent=2) + "\n"
|
|
327
448
|
|
|
328
449
|
|
|
@@ -392,7 +513,12 @@ def print_bundle_summary(config: DeployConfig, build_dir: Path) -> None:
|
|
|
392
513
|
print(f"\n Agent: {config.agent.name}")
|
|
393
514
|
print(f" Model: {config.agent.model}")
|
|
394
515
|
if config.auth is not None:
|
|
395
|
-
|
|
516
|
+
if config.auth.provider == "anonymous":
|
|
517
|
+
print(" Auth: anonymous (API open to anyone)")
|
|
518
|
+
else:
|
|
519
|
+
print(f" Auth: {config.auth.provider}")
|
|
520
|
+
else:
|
|
521
|
+
print(" Auth: none (LangSmith API key required to call the API)")
|
|
396
522
|
|
|
397
523
|
memory_files = sorted(seed.get("memories", {}).keys())
|
|
398
524
|
if memory_files:
|
|
@@ -265,6 +265,51 @@ def _deploy(
|
|
|
265
265
|
print(f" - {err}")
|
|
266
266
|
raise SystemExit(1)
|
|
267
267
|
|
|
268
|
+
# Warn + confirm if the frontend was set to anonymous mode. The
|
|
269
|
+
# generated auth.py for this case is permissive (overrides the
|
|
270
|
+
# LangSmith default x-api-key requirement) so the API is reachable
|
|
271
|
+
# by anyone with the deploy URL.
|
|
272
|
+
is_anonymous = (
|
|
273
|
+
config.frontend is not None
|
|
274
|
+
and config.frontend.enabled
|
|
275
|
+
and config.auth is not None
|
|
276
|
+
and config.auth.provider == "anonymous"
|
|
277
|
+
)
|
|
278
|
+
if is_anonymous:
|
|
279
|
+
# ANSI bold-red header + red bullets so this warning is visually
|
|
280
|
+
# distinct from the yellow beta-warning that prints above it
|
|
281
|
+
# (otherwise the "Continue? [y/N]" prompt looks like it's
|
|
282
|
+
# confirming the beta line rather than the anonymous-auth line).
|
|
283
|
+
print(
|
|
284
|
+
"\033[1;31m⚠ This deploy will use ANONYMOUS auth. "
|
|
285
|
+
"The API is open to anyone with the deploy URL.\033[0m"
|
|
286
|
+
)
|
|
287
|
+
print(
|
|
288
|
+
"\033[31m • Browser UI shows per-browser threads "
|
|
289
|
+
"(cookie-scoped UX, not security).\033[0m"
|
|
290
|
+
)
|
|
291
|
+
print(
|
|
292
|
+
"\033[31m • Anyone with the URL can call the API directly "
|
|
293
|
+
"(curl /threads, /runs, etc.) — no auth.\033[0m"
|
|
294
|
+
)
|
|
295
|
+
print(
|
|
296
|
+
"\033[31m • For real per-user auth, add an [auth] section "
|
|
297
|
+
'(provider = "supabase" or "clerk").\033[0m'
|
|
298
|
+
)
|
|
299
|
+
# Skip the interactive confirm on dry-run (no real push happens).
|
|
300
|
+
if not dry_run:
|
|
301
|
+
try:
|
|
302
|
+
answer = (
|
|
303
|
+
input("Continue with anonymous deploy? [y/N]: ").strip().lower()
|
|
304
|
+
)
|
|
305
|
+
except (EOFError, KeyboardInterrupt):
|
|
306
|
+
print()
|
|
307
|
+
print("Aborted.")
|
|
308
|
+
raise SystemExit(1) from None
|
|
309
|
+
if answer not in {"y", "yes"}:
|
|
310
|
+
print("Aborted.")
|
|
311
|
+
raise SystemExit(1)
|
|
312
|
+
|
|
268
313
|
# Bundle
|
|
269
314
|
build_dir = Path(tempfile.mkdtemp(prefix="deepagents-deploy-"))
|
|
270
315
|
|
|
@@ -36,8 +36,14 @@ VALID_SANDBOX_PROVIDERS: frozenset[str] = frozenset(get_args(SandboxProvider))
|
|
|
36
36
|
|
|
37
37
|
VALID_SANDBOX_SCOPES: frozenset[str] = frozenset(get_args(SandboxScope))
|
|
38
38
|
|
|
39
|
-
AuthProvider = Literal["supabase", "clerk"]
|
|
40
|
-
"""Valid auth provider identifiers.
|
|
39
|
+
AuthProvider = Literal["supabase", "clerk", "anonymous"]
|
|
40
|
+
"""Valid auth provider identifiers.
|
|
41
|
+
|
|
42
|
+
`"anonymous"` ships a permissive auth handler that overrides LangSmith
|
|
43
|
+
Cloud's default `x-api-key` requirement so the bundled frontend can
|
|
44
|
+
reach `/threads`. The API is open to anyone with the deploy URL —
|
|
45
|
+
per-browser thread scoping is enforced client-side via a UUID cookie.
|
|
46
|
+
"""
|
|
41
47
|
|
|
42
48
|
VALID_AUTH_PROVIDERS: frozenset[str] = frozenset(get_args(AuthProvider))
|
|
43
49
|
"""Valid auth providers for deploy."""
|
|
@@ -121,13 +127,38 @@ class SandboxConfig:
|
|
|
121
127
|
class AuthConfig:
|
|
122
128
|
"""`[auth]` section — authentication provider settings.
|
|
123
129
|
|
|
124
|
-
The whole section is optional. When omitted,
|
|
125
|
-
|
|
130
|
+
The whole section is optional. When omitted, no `auth.py` is
|
|
131
|
+
generated and LangSmith Cloud's default `x-api-key` auth applies
|
|
132
|
+
(callers still need a LangSmith API key to reach the deployment).
|
|
133
|
+
To make the API genuinely open — e.g., to expose the bundled
|
|
134
|
+
`[frontend]` without sign-in — set `provider = "anonymous"`
|
|
135
|
+
explicitly.
|
|
126
136
|
"""
|
|
127
137
|
|
|
128
138
|
provider: AuthProvider
|
|
129
139
|
|
|
130
140
|
|
|
141
|
+
@dataclass(frozen=True)
|
|
142
|
+
class FrontendConfig:
|
|
143
|
+
"""`[frontend]` section — bundled default frontend settings.
|
|
144
|
+
|
|
145
|
+
When `enabled = True`, `deepagent deploy` copies a pre-built React
|
|
146
|
+
chat UI into the deployment alongside the agent. An `[auth]`
|
|
147
|
+
section is required in this case — pick `"supabase"` or `"clerk"`
|
|
148
|
+
for real per-user auth, or set `provider = "anonymous"` explicitly
|
|
149
|
+
to ship the UI with an open API.
|
|
150
|
+
"""
|
|
151
|
+
|
|
152
|
+
enabled: bool = False
|
|
153
|
+
app_name: str | None = None
|
|
154
|
+
subtitle: str | None = None
|
|
155
|
+
"""Subtitle shown under the app name in the header and on the
|
|
156
|
+
empty-state hero. Falls back to a generic default when unset."""
|
|
157
|
+
prompts: tuple[str, ...] | None = None
|
|
158
|
+
"""Suggestion chips shown on the empty-state. Falls back to the
|
|
159
|
+
bundled defaults when unset."""
|
|
160
|
+
|
|
161
|
+
|
|
131
162
|
@dataclass(frozen=True)
|
|
132
163
|
class DeployConfig:
|
|
133
164
|
"""Top-level deploy configuration parsed from `deepagents.toml`."""
|
|
@@ -138,6 +169,7 @@ class DeployConfig:
|
|
|
138
169
|
sandbox: SandboxConfig = field(default_factory=SandboxConfig)
|
|
139
170
|
"""Parsed `[sandbox]` section — provider, snapshot name, image, scope."""
|
|
140
171
|
auth: AuthConfig | None = None
|
|
172
|
+
frontend: FrontendConfig | None = None
|
|
141
173
|
|
|
142
174
|
def validate(self, project_root: Path) -> list[str]:
|
|
143
175
|
"""Validate config against the filesystem.
|
|
@@ -194,6 +226,16 @@ class DeployConfig:
|
|
|
194
226
|
if self.auth is not None:
|
|
195
227
|
errors.extend(_validate_auth_credentials(self.auth.provider))
|
|
196
228
|
|
|
229
|
+
if self.frontend is not None and self.frontend.enabled:
|
|
230
|
+
if self.auth is None:
|
|
231
|
+
errors.append(
|
|
232
|
+
"[frontend].enabled requires [auth] to be configured. "
|
|
233
|
+
'Add an [auth] section with provider = "supabase", '
|
|
234
|
+
'"clerk", or "anonymous".'
|
|
235
|
+
)
|
|
236
|
+
else:
|
|
237
|
+
errors.extend(_validate_frontend_credentials(self.auth.provider))
|
|
238
|
+
|
|
197
239
|
return errors
|
|
198
240
|
|
|
199
241
|
|
|
@@ -363,10 +405,11 @@ def load_config(config_path: Path) -> DeployConfig:
|
|
|
363
405
|
return _parse_config(data)
|
|
364
406
|
|
|
365
407
|
|
|
366
|
-
_ALLOWED_SECTIONS = frozenset({"agent", "sandbox", "auth"})
|
|
408
|
+
_ALLOWED_SECTIONS = frozenset({"agent", "sandbox", "auth", "frontend"})
|
|
367
409
|
_ALLOWED_AGENT_KEYS = frozenset({"name", "description", "model"})
|
|
368
410
|
_ALLOWED_SANDBOX_KEYS = frozenset({"provider", "template", "image", "scope"})
|
|
369
411
|
_ALLOWED_AUTH_KEYS = frozenset({"provider"})
|
|
412
|
+
_ALLOWED_FRONTEND_KEYS = frozenset({"enabled", "app_name", "subtitle", "prompts"})
|
|
370
413
|
|
|
371
414
|
|
|
372
415
|
def _parse_config(data: dict[str, Any]) -> DeployConfig:
|
|
@@ -442,7 +485,33 @@ def _parse_config(data: dict[str, Any]) -> DeployConfig:
|
|
|
442
485
|
|
|
443
486
|
auth = AuthConfig(provider=auth_provider)
|
|
444
487
|
|
|
445
|
-
|
|
488
|
+
frontend: FrontendConfig | None = None
|
|
489
|
+
frontend_data = data.get("frontend")
|
|
490
|
+
if frontend_data is not None:
|
|
491
|
+
unknown_frontend = set(frontend_data.keys()) - _ALLOWED_FRONTEND_KEYS
|
|
492
|
+
if unknown_frontend:
|
|
493
|
+
msg = (
|
|
494
|
+
f"Unknown key(s) in [frontend]: {sorted(unknown_frontend)}. "
|
|
495
|
+
f"Allowed: {sorted(_ALLOWED_FRONTEND_KEYS)}"
|
|
496
|
+
)
|
|
497
|
+
raise ValueError(msg)
|
|
498
|
+
|
|
499
|
+
frontend_kwargs: dict[str, Any] = {
|
|
500
|
+
k: frontend_data[k] for k in _ALLOWED_FRONTEND_KEYS if k in frontend_data
|
|
501
|
+
}
|
|
502
|
+
# FrontendConfig is frozen=True; coerce list -> tuple so the
|
|
503
|
+
# dataclass stays hashable.
|
|
504
|
+
if "prompts" in frontend_kwargs:
|
|
505
|
+
prompts_raw = frontend_kwargs["prompts"]
|
|
506
|
+
if not isinstance(prompts_raw, list) or not all(
|
|
507
|
+
isinstance(p, str) for p in prompts_raw
|
|
508
|
+
):
|
|
509
|
+
msg = "[frontend].prompts must be a list of strings"
|
|
510
|
+
raise ValueError(msg)
|
|
511
|
+
frontend_kwargs["prompts"] = tuple(prompts_raw)
|
|
512
|
+
frontend = FrontendConfig(**frontend_kwargs)
|
|
513
|
+
|
|
514
|
+
return DeployConfig(agent=agent, sandbox=sandbox, auth=auth, frontend=frontend)
|
|
446
515
|
|
|
447
516
|
|
|
448
517
|
_MODEL_PROVIDER_ENV: dict[str, str] = {
|
|
@@ -480,6 +549,16 @@ _AUTH_PROVIDER_ENV: dict[str, list[str]] = {
|
|
|
480
549
|
"clerk": ["CLERK_SECRET_KEY"],
|
|
481
550
|
}
|
|
482
551
|
|
|
552
|
+
_FRONTEND_EXTRA_ENV: dict[str, list[str]] = {
|
|
553
|
+
# Supabase reuses `SUPABASE_URL` + `SUPABASE_PUBLISHABLE_DEFAULT_KEY`
|
|
554
|
+
# from [auth] — no extra browser-facing env vars needed.
|
|
555
|
+
"supabase": [],
|
|
556
|
+
# Clerk's browser-facing publishable key is distinct from
|
|
557
|
+
# `CLERK_SECRET_KEY` (which [auth] uses for JWKS validation).
|
|
558
|
+
"clerk": ["CLERK_PUBLISHABLE_KEY"],
|
|
559
|
+
}
|
|
560
|
+
"""Additional env vars the frontend bundle needs beyond what `[auth]` requires."""
|
|
561
|
+
|
|
483
562
|
|
|
484
563
|
def _validate_model_credentials(model: str) -> list[str]:
|
|
485
564
|
"""Check that the API key env var is set for the model provider."""
|
|
@@ -530,6 +609,23 @@ def _validate_auth_credentials(provider: str) -> list[str]:
|
|
|
530
609
|
]
|
|
531
610
|
|
|
532
611
|
|
|
612
|
+
def _validate_frontend_credentials(provider: str) -> list[str]:
|
|
613
|
+
"""Check that all extra env vars are set for the frontend bundle."""
|
|
614
|
+
required = _FRONTEND_EXTRA_ENV.get(provider)
|
|
615
|
+
if required is None:
|
|
616
|
+
return []
|
|
617
|
+
missing = [v for v in required if not os.environ.get(v)]
|
|
618
|
+
if not missing:
|
|
619
|
+
return []
|
|
620
|
+
return [
|
|
621
|
+
(
|
|
622
|
+
f"Frontend for '{provider}' requires {' and '.join(missing)}. "
|
|
623
|
+
f"Add it to your .env file so the bundler can write it "
|
|
624
|
+
f"into index.html at deploy time."
|
|
625
|
+
),
|
|
626
|
+
]
|
|
627
|
+
|
|
628
|
+
|
|
533
629
|
def find_config(start_path: Path | None = None) -> Path | None:
|
|
534
630
|
"""Find `deepagents.toml` in *start_path* (or cwd if not given).
|
|
535
631
|
|
|
@@ -558,7 +654,16 @@ model = "anthropic:claude-sonnet-4-6"
|
|
|
558
654
|
|
|
559
655
|
# [auth] is optional. Add to enable user authentication.
|
|
560
656
|
# [auth]
|
|
561
|
-
# provider = "supabase" # supabase | clerk
|
|
657
|
+
# provider = "supabase" # supabase | clerk | anonymous
|
|
658
|
+
|
|
659
|
+
# [frontend] is optional. Add to ship a bundled chat UI on the same
|
|
660
|
+
# deployment as the agent. Requires [auth] — pick "supabase" or
|
|
661
|
+
# "clerk" for real per-user auth, or set provider = "anonymous" to
|
|
662
|
+
# leave the API open to anyone with the deploy URL (private/dev
|
|
663
|
+
# deploys only).
|
|
664
|
+
# [frontend]
|
|
665
|
+
# enabled = true
|
|
666
|
+
# app_name = "My Agent"
|
|
562
667
|
"""
|
|
563
668
|
|
|
564
669
|
|
|
@@ -589,6 +694,10 @@ LANGSMITH_API_KEY=
|
|
|
589
694
|
# SUPABASE_URL=
|
|
590
695
|
# SUPABASE_PUBLISHABLE_DEFAULT_KEY=
|
|
591
696
|
# CLERK_SECRET_KEY=
|
|
697
|
+
|
|
698
|
+
# Frontend (optional, uncomment for [frontend] + matching [auth])
|
|
699
|
+
# Clerk only — browser-facing publishable key. Supabase reuses the keys above.
|
|
700
|
+
# CLERK_PUBLISHABLE_KEY=
|
|
592
701
|
"""
|
|
593
702
|
|
|
594
703
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{j as o}from"./index-DM3gptpu.js";const i="dap_anon_id";function s(n){if(typeof document>"u")return null;const e=n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),t=document.cookie.match(new RegExp(`(?:^|; )${e}=([^;]*)`));return t?decodeURIComponent(t[1]):null}function r(n,e){typeof document>"u"||(document.cookie=`${n}=${encodeURIComponent(e)}; max-age=31536000; path=/; SameSite=Lax`)}function u(){if(typeof crypto>"u")return"anon";const n=s(i);if(n)return n;const e=crypto.randomUUID();return r(i,e),e}const c={status:"signed-in",accessToken:"",userIdentity:u(),userEmail:null,isAnonymous:!0,signOut:async()=>{}},a={Provider:({children:n})=>o.jsx(o.Fragment,{children:n}),useSession:()=>c,AuthUI:()=>null};export{a as default};
|