PraisonAI 3.0.0__py3-none-any.whl
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.
- praisonai/__init__.py +54 -0
- praisonai/__main__.py +15 -0
- praisonai/acp/__init__.py +54 -0
- praisonai/acp/config.py +159 -0
- praisonai/acp/server.py +587 -0
- praisonai/acp/session.py +219 -0
- praisonai/adapters/__init__.py +50 -0
- praisonai/adapters/readers.py +395 -0
- praisonai/adapters/rerankers.py +315 -0
- praisonai/adapters/retrievers.py +394 -0
- praisonai/adapters/vector_stores.py +409 -0
- praisonai/agent_scheduler.py +337 -0
- praisonai/agents_generator.py +903 -0
- praisonai/api/call.py +292 -0
- praisonai/auto.py +1197 -0
- praisonai/capabilities/__init__.py +275 -0
- praisonai/capabilities/a2a.py +140 -0
- praisonai/capabilities/assistants.py +283 -0
- praisonai/capabilities/audio.py +320 -0
- praisonai/capabilities/batches.py +469 -0
- praisonai/capabilities/completions.py +336 -0
- praisonai/capabilities/container_files.py +155 -0
- praisonai/capabilities/containers.py +93 -0
- praisonai/capabilities/embeddings.py +158 -0
- praisonai/capabilities/files.py +467 -0
- praisonai/capabilities/fine_tuning.py +293 -0
- praisonai/capabilities/guardrails.py +182 -0
- praisonai/capabilities/images.py +330 -0
- praisonai/capabilities/mcp.py +190 -0
- praisonai/capabilities/messages.py +270 -0
- praisonai/capabilities/moderations.py +154 -0
- praisonai/capabilities/ocr.py +217 -0
- praisonai/capabilities/passthrough.py +204 -0
- praisonai/capabilities/rag.py +207 -0
- praisonai/capabilities/realtime.py +160 -0
- praisonai/capabilities/rerank.py +165 -0
- praisonai/capabilities/responses.py +266 -0
- praisonai/capabilities/search.py +109 -0
- praisonai/capabilities/skills.py +133 -0
- praisonai/capabilities/vector_store_files.py +334 -0
- praisonai/capabilities/vector_stores.py +304 -0
- praisonai/capabilities/videos.py +141 -0
- praisonai/chainlit_ui.py +304 -0
- praisonai/chat/__init__.py +106 -0
- praisonai/chat/app.py +125 -0
- praisonai/cli/__init__.py +26 -0
- praisonai/cli/app.py +213 -0
- praisonai/cli/commands/__init__.py +75 -0
- praisonai/cli/commands/acp.py +70 -0
- praisonai/cli/commands/completion.py +333 -0
- praisonai/cli/commands/config.py +166 -0
- praisonai/cli/commands/debug.py +142 -0
- praisonai/cli/commands/diag.py +55 -0
- praisonai/cli/commands/doctor.py +166 -0
- praisonai/cli/commands/environment.py +179 -0
- praisonai/cli/commands/lsp.py +112 -0
- praisonai/cli/commands/mcp.py +210 -0
- praisonai/cli/commands/profile.py +457 -0
- praisonai/cli/commands/run.py +228 -0
- praisonai/cli/commands/schedule.py +150 -0
- praisonai/cli/commands/serve.py +97 -0
- praisonai/cli/commands/session.py +212 -0
- praisonai/cli/commands/traces.py +145 -0
- praisonai/cli/commands/version.py +101 -0
- praisonai/cli/configuration/__init__.py +18 -0
- praisonai/cli/configuration/loader.py +353 -0
- praisonai/cli/configuration/paths.py +114 -0
- praisonai/cli/configuration/schema.py +164 -0
- praisonai/cli/features/__init__.py +268 -0
- praisonai/cli/features/acp.py +236 -0
- praisonai/cli/features/action_orchestrator.py +546 -0
- praisonai/cli/features/agent_scheduler.py +773 -0
- praisonai/cli/features/agent_tools.py +474 -0
- praisonai/cli/features/agents.py +375 -0
- praisonai/cli/features/at_mentions.py +471 -0
- praisonai/cli/features/auto_memory.py +182 -0
- praisonai/cli/features/autonomy_mode.py +490 -0
- praisonai/cli/features/background.py +356 -0
- praisonai/cli/features/base.py +168 -0
- praisonai/cli/features/capabilities.py +1326 -0
- praisonai/cli/features/checkpoints.py +338 -0
- praisonai/cli/features/code_intelligence.py +652 -0
- praisonai/cli/features/compaction.py +294 -0
- praisonai/cli/features/compare.py +534 -0
- praisonai/cli/features/cost_tracker.py +514 -0
- praisonai/cli/features/debug.py +810 -0
- praisonai/cli/features/deploy.py +517 -0
- praisonai/cli/features/diag.py +289 -0
- praisonai/cli/features/doctor/__init__.py +63 -0
- praisonai/cli/features/doctor/checks/__init__.py +24 -0
- praisonai/cli/features/doctor/checks/acp_checks.py +240 -0
- praisonai/cli/features/doctor/checks/config_checks.py +366 -0
- praisonai/cli/features/doctor/checks/db_checks.py +366 -0
- praisonai/cli/features/doctor/checks/env_checks.py +543 -0
- praisonai/cli/features/doctor/checks/lsp_checks.py +199 -0
- praisonai/cli/features/doctor/checks/mcp_checks.py +349 -0
- praisonai/cli/features/doctor/checks/memory_checks.py +268 -0
- praisonai/cli/features/doctor/checks/network_checks.py +251 -0
- praisonai/cli/features/doctor/checks/obs_checks.py +328 -0
- praisonai/cli/features/doctor/checks/performance_checks.py +235 -0
- praisonai/cli/features/doctor/checks/permissions_checks.py +259 -0
- praisonai/cli/features/doctor/checks/selftest_checks.py +322 -0
- praisonai/cli/features/doctor/checks/serve_checks.py +426 -0
- praisonai/cli/features/doctor/checks/skills_checks.py +231 -0
- praisonai/cli/features/doctor/checks/tools_checks.py +371 -0
- praisonai/cli/features/doctor/engine.py +266 -0
- praisonai/cli/features/doctor/formatters.py +310 -0
- praisonai/cli/features/doctor/handler.py +397 -0
- praisonai/cli/features/doctor/models.py +264 -0
- praisonai/cli/features/doctor/registry.py +239 -0
- praisonai/cli/features/endpoints.py +1019 -0
- praisonai/cli/features/eval.py +560 -0
- praisonai/cli/features/external_agents.py +231 -0
- praisonai/cli/features/fast_context.py +410 -0
- praisonai/cli/features/flow_display.py +566 -0
- praisonai/cli/features/git_integration.py +651 -0
- praisonai/cli/features/guardrail.py +171 -0
- praisonai/cli/features/handoff.py +185 -0
- praisonai/cli/features/hooks.py +583 -0
- praisonai/cli/features/image.py +384 -0
- praisonai/cli/features/interactive_runtime.py +585 -0
- praisonai/cli/features/interactive_tools.py +380 -0
- praisonai/cli/features/interactive_tui.py +603 -0
- praisonai/cli/features/jobs.py +632 -0
- praisonai/cli/features/knowledge.py +531 -0
- praisonai/cli/features/lite.py +244 -0
- praisonai/cli/features/lsp_cli.py +225 -0
- praisonai/cli/features/mcp.py +169 -0
- praisonai/cli/features/message_queue.py +587 -0
- praisonai/cli/features/metrics.py +211 -0
- praisonai/cli/features/n8n.py +673 -0
- praisonai/cli/features/observability.py +293 -0
- praisonai/cli/features/ollama.py +361 -0
- praisonai/cli/features/output_style.py +273 -0
- praisonai/cli/features/package.py +631 -0
- praisonai/cli/features/performance.py +308 -0
- praisonai/cli/features/persistence.py +636 -0
- praisonai/cli/features/profile.py +226 -0
- praisonai/cli/features/profiler/__init__.py +81 -0
- praisonai/cli/features/profiler/core.py +558 -0
- praisonai/cli/features/profiler/optimizations.py +652 -0
- praisonai/cli/features/profiler/suite.py +386 -0
- praisonai/cli/features/profiling.py +350 -0
- praisonai/cli/features/queue/__init__.py +73 -0
- praisonai/cli/features/queue/manager.py +395 -0
- praisonai/cli/features/queue/models.py +286 -0
- praisonai/cli/features/queue/persistence.py +564 -0
- praisonai/cli/features/queue/scheduler.py +484 -0
- praisonai/cli/features/queue/worker.py +372 -0
- praisonai/cli/features/recipe.py +1723 -0
- praisonai/cli/features/recipes.py +449 -0
- praisonai/cli/features/registry.py +229 -0
- praisonai/cli/features/repo_map.py +860 -0
- praisonai/cli/features/router.py +466 -0
- praisonai/cli/features/sandbox_executor.py +515 -0
- praisonai/cli/features/serve.py +829 -0
- praisonai/cli/features/session.py +222 -0
- praisonai/cli/features/skills.py +856 -0
- praisonai/cli/features/slash_commands.py +650 -0
- praisonai/cli/features/telemetry.py +179 -0
- praisonai/cli/features/templates.py +1384 -0
- praisonai/cli/features/thinking.py +305 -0
- praisonai/cli/features/todo.py +334 -0
- praisonai/cli/features/tools.py +680 -0
- praisonai/cli/features/tui/__init__.py +83 -0
- praisonai/cli/features/tui/app.py +580 -0
- praisonai/cli/features/tui/cli.py +566 -0
- praisonai/cli/features/tui/debug.py +511 -0
- praisonai/cli/features/tui/events.py +99 -0
- praisonai/cli/features/tui/mock_provider.py +328 -0
- praisonai/cli/features/tui/orchestrator.py +652 -0
- praisonai/cli/features/tui/screens/__init__.py +50 -0
- praisonai/cli/features/tui/screens/main.py +245 -0
- praisonai/cli/features/tui/screens/queue.py +174 -0
- praisonai/cli/features/tui/screens/session.py +124 -0
- praisonai/cli/features/tui/screens/settings.py +148 -0
- praisonai/cli/features/tui/widgets/__init__.py +56 -0
- praisonai/cli/features/tui/widgets/chat.py +261 -0
- praisonai/cli/features/tui/widgets/composer.py +224 -0
- praisonai/cli/features/tui/widgets/queue_panel.py +200 -0
- praisonai/cli/features/tui/widgets/status.py +167 -0
- praisonai/cli/features/tui/widgets/tool_panel.py +248 -0
- praisonai/cli/features/workflow.py +720 -0
- praisonai/cli/legacy.py +236 -0
- praisonai/cli/main.py +5559 -0
- praisonai/cli/schedule_cli.py +54 -0
- praisonai/cli/state/__init__.py +31 -0
- praisonai/cli/state/identifiers.py +161 -0
- praisonai/cli/state/sessions.py +313 -0
- praisonai/code/__init__.py +93 -0
- praisonai/code/agent_tools.py +344 -0
- praisonai/code/diff/__init__.py +21 -0
- praisonai/code/diff/diff_strategy.py +432 -0
- praisonai/code/tools/__init__.py +27 -0
- praisonai/code/tools/apply_diff.py +221 -0
- praisonai/code/tools/execute_command.py +275 -0
- praisonai/code/tools/list_files.py +274 -0
- praisonai/code/tools/read_file.py +206 -0
- praisonai/code/tools/search_replace.py +248 -0
- praisonai/code/tools/write_file.py +217 -0
- praisonai/code/utils/__init__.py +46 -0
- praisonai/code/utils/file_utils.py +307 -0
- praisonai/code/utils/ignore_utils.py +308 -0
- praisonai/code/utils/text_utils.py +276 -0
- praisonai/db/__init__.py +64 -0
- praisonai/db/adapter.py +531 -0
- praisonai/deploy/__init__.py +62 -0
- praisonai/deploy/api.py +231 -0
- praisonai/deploy/docker.py +454 -0
- praisonai/deploy/doctor.py +367 -0
- praisonai/deploy/main.py +327 -0
- praisonai/deploy/models.py +179 -0
- praisonai/deploy/providers/__init__.py +33 -0
- praisonai/deploy/providers/aws.py +331 -0
- praisonai/deploy/providers/azure.py +358 -0
- praisonai/deploy/providers/base.py +101 -0
- praisonai/deploy/providers/gcp.py +314 -0
- praisonai/deploy/schema.py +208 -0
- praisonai/deploy.py +185 -0
- praisonai/endpoints/__init__.py +53 -0
- praisonai/endpoints/a2u_server.py +410 -0
- praisonai/endpoints/discovery.py +165 -0
- praisonai/endpoints/providers/__init__.py +28 -0
- praisonai/endpoints/providers/a2a.py +253 -0
- praisonai/endpoints/providers/a2u.py +208 -0
- praisonai/endpoints/providers/agents_api.py +171 -0
- praisonai/endpoints/providers/base.py +231 -0
- praisonai/endpoints/providers/mcp.py +263 -0
- praisonai/endpoints/providers/recipe.py +206 -0
- praisonai/endpoints/providers/tools_mcp.py +150 -0
- praisonai/endpoints/registry.py +131 -0
- praisonai/endpoints/server.py +161 -0
- praisonai/inbuilt_tools/__init__.py +24 -0
- praisonai/inbuilt_tools/autogen_tools.py +117 -0
- praisonai/inc/__init__.py +2 -0
- praisonai/inc/config.py +96 -0
- praisonai/inc/models.py +155 -0
- praisonai/integrations/__init__.py +56 -0
- praisonai/integrations/base.py +303 -0
- praisonai/integrations/claude_code.py +270 -0
- praisonai/integrations/codex_cli.py +255 -0
- praisonai/integrations/cursor_cli.py +195 -0
- praisonai/integrations/gemini_cli.py +222 -0
- praisonai/jobs/__init__.py +67 -0
- praisonai/jobs/executor.py +425 -0
- praisonai/jobs/models.py +230 -0
- praisonai/jobs/router.py +314 -0
- praisonai/jobs/server.py +186 -0
- praisonai/jobs/store.py +203 -0
- praisonai/llm/__init__.py +66 -0
- praisonai/llm/registry.py +382 -0
- praisonai/mcp_server/__init__.py +152 -0
- praisonai/mcp_server/adapters/__init__.py +74 -0
- praisonai/mcp_server/adapters/agents.py +128 -0
- praisonai/mcp_server/adapters/capabilities.py +168 -0
- praisonai/mcp_server/adapters/cli_tools.py +568 -0
- praisonai/mcp_server/adapters/extended_capabilities.py +462 -0
- praisonai/mcp_server/adapters/knowledge.py +93 -0
- praisonai/mcp_server/adapters/memory.py +104 -0
- praisonai/mcp_server/adapters/prompts.py +306 -0
- praisonai/mcp_server/adapters/resources.py +124 -0
- praisonai/mcp_server/adapters/tools_bridge.py +280 -0
- praisonai/mcp_server/auth/__init__.py +48 -0
- praisonai/mcp_server/auth/api_key.py +291 -0
- praisonai/mcp_server/auth/oauth.py +460 -0
- praisonai/mcp_server/auth/oidc.py +289 -0
- praisonai/mcp_server/auth/scopes.py +260 -0
- praisonai/mcp_server/cli.py +852 -0
- praisonai/mcp_server/elicitation.py +445 -0
- praisonai/mcp_server/icons.py +302 -0
- praisonai/mcp_server/recipe_adapter.py +573 -0
- praisonai/mcp_server/recipe_cli.py +824 -0
- praisonai/mcp_server/registry.py +703 -0
- praisonai/mcp_server/sampling.py +422 -0
- praisonai/mcp_server/server.py +490 -0
- praisonai/mcp_server/tasks.py +443 -0
- praisonai/mcp_server/transports/__init__.py +18 -0
- praisonai/mcp_server/transports/http_stream.py +376 -0
- praisonai/mcp_server/transports/stdio.py +132 -0
- praisonai/persistence/__init__.py +84 -0
- praisonai/persistence/config.py +238 -0
- praisonai/persistence/conversation/__init__.py +25 -0
- praisonai/persistence/conversation/async_mysql.py +427 -0
- praisonai/persistence/conversation/async_postgres.py +410 -0
- praisonai/persistence/conversation/async_sqlite.py +371 -0
- praisonai/persistence/conversation/base.py +151 -0
- praisonai/persistence/conversation/json_store.py +250 -0
- praisonai/persistence/conversation/mysql.py +387 -0
- praisonai/persistence/conversation/postgres.py +401 -0
- praisonai/persistence/conversation/singlestore.py +240 -0
- praisonai/persistence/conversation/sqlite.py +341 -0
- praisonai/persistence/conversation/supabase.py +203 -0
- praisonai/persistence/conversation/surrealdb.py +287 -0
- praisonai/persistence/factory.py +301 -0
- praisonai/persistence/hooks/__init__.py +18 -0
- praisonai/persistence/hooks/agent_hooks.py +297 -0
- praisonai/persistence/knowledge/__init__.py +26 -0
- praisonai/persistence/knowledge/base.py +144 -0
- praisonai/persistence/knowledge/cassandra.py +232 -0
- praisonai/persistence/knowledge/chroma.py +295 -0
- praisonai/persistence/knowledge/clickhouse.py +242 -0
- praisonai/persistence/knowledge/cosmosdb_vector.py +438 -0
- praisonai/persistence/knowledge/couchbase.py +286 -0
- praisonai/persistence/knowledge/lancedb.py +216 -0
- praisonai/persistence/knowledge/langchain_adapter.py +291 -0
- praisonai/persistence/knowledge/lightrag_adapter.py +212 -0
- praisonai/persistence/knowledge/llamaindex_adapter.py +256 -0
- praisonai/persistence/knowledge/milvus.py +277 -0
- praisonai/persistence/knowledge/mongodb_vector.py +306 -0
- praisonai/persistence/knowledge/pgvector.py +335 -0
- praisonai/persistence/knowledge/pinecone.py +253 -0
- praisonai/persistence/knowledge/qdrant.py +301 -0
- praisonai/persistence/knowledge/redis_vector.py +291 -0
- praisonai/persistence/knowledge/singlestore_vector.py +299 -0
- praisonai/persistence/knowledge/surrealdb_vector.py +309 -0
- praisonai/persistence/knowledge/upstash_vector.py +266 -0
- praisonai/persistence/knowledge/weaviate.py +223 -0
- praisonai/persistence/migrations/__init__.py +10 -0
- praisonai/persistence/migrations/manager.py +251 -0
- praisonai/persistence/orchestrator.py +406 -0
- praisonai/persistence/state/__init__.py +21 -0
- praisonai/persistence/state/async_mongodb.py +200 -0
- praisonai/persistence/state/base.py +107 -0
- praisonai/persistence/state/dynamodb.py +226 -0
- praisonai/persistence/state/firestore.py +175 -0
- praisonai/persistence/state/gcs.py +155 -0
- praisonai/persistence/state/memory.py +245 -0
- praisonai/persistence/state/mongodb.py +158 -0
- praisonai/persistence/state/redis.py +190 -0
- praisonai/persistence/state/upstash.py +144 -0
- praisonai/persistence/tests/__init__.py +3 -0
- praisonai/persistence/tests/test_all_backends.py +633 -0
- praisonai/profiler.py +1214 -0
- praisonai/recipe/__init__.py +134 -0
- praisonai/recipe/bridge.py +278 -0
- praisonai/recipe/core.py +893 -0
- praisonai/recipe/exceptions.py +54 -0
- praisonai/recipe/history.py +402 -0
- praisonai/recipe/models.py +266 -0
- praisonai/recipe/operations.py +440 -0
- praisonai/recipe/policy.py +422 -0
- praisonai/recipe/registry.py +849 -0
- praisonai/recipe/runtime.py +214 -0
- praisonai/recipe/security.py +711 -0
- praisonai/recipe/serve.py +859 -0
- praisonai/recipe/server.py +613 -0
- praisonai/scheduler/__init__.py +45 -0
- praisonai/scheduler/agent_scheduler.py +552 -0
- praisonai/scheduler/base.py +124 -0
- praisonai/scheduler/daemon_manager.py +225 -0
- praisonai/scheduler/state_manager.py +155 -0
- praisonai/scheduler/yaml_loader.py +193 -0
- praisonai/scheduler.py +194 -0
- praisonai/setup/__init__.py +1 -0
- praisonai/setup/build.py +21 -0
- praisonai/setup/post_install.py +23 -0
- praisonai/setup/setup_conda_env.py +25 -0
- praisonai/setup.py +16 -0
- praisonai/templates/__init__.py +116 -0
- praisonai/templates/cache.py +364 -0
- praisonai/templates/dependency_checker.py +358 -0
- praisonai/templates/discovery.py +391 -0
- praisonai/templates/loader.py +564 -0
- praisonai/templates/registry.py +511 -0
- praisonai/templates/resolver.py +206 -0
- praisonai/templates/security.py +327 -0
- praisonai/templates/tool_override.py +498 -0
- praisonai/templates/tools_doctor.py +256 -0
- praisonai/test.py +105 -0
- praisonai/train.py +562 -0
- praisonai/train_vision.py +306 -0
- praisonai/ui/agents.py +824 -0
- praisonai/ui/callbacks.py +57 -0
- praisonai/ui/chainlit_compat.py +246 -0
- praisonai/ui/chat.py +532 -0
- praisonai/ui/code.py +717 -0
- praisonai/ui/colab.py +474 -0
- praisonai/ui/colab_chainlit.py +81 -0
- praisonai/ui/components/aicoder.py +284 -0
- praisonai/ui/context.py +283 -0
- praisonai/ui/database_config.py +56 -0
- praisonai/ui/db.py +294 -0
- praisonai/ui/realtime.py +488 -0
- praisonai/ui/realtimeclient/__init__.py +756 -0
- praisonai/ui/realtimeclient/tools.py +242 -0
- praisonai/ui/sql_alchemy.py +710 -0
- praisonai/upload_vision.py +140 -0
- praisonai/version.py +1 -0
- praisonai-3.0.0.dist-info/METADATA +3493 -0
- praisonai-3.0.0.dist-info/RECORD +393 -0
- praisonai-3.0.0.dist-info/WHEEL +5 -0
- praisonai-3.0.0.dist-info/entry_points.txt +4 -0
- praisonai-3.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
"""
|
|
2
|
+
GCP provider for cloud deployment (Cloud Run).
|
|
3
|
+
"""
|
|
4
|
+
import subprocess
|
|
5
|
+
import json
|
|
6
|
+
from typing import Dict, Any
|
|
7
|
+
from .base import BaseProvider
|
|
8
|
+
from ..models import DeployResult, DeployStatus, DestroyResult, ServiceState
|
|
9
|
+
from ..doctor import DoctorReport, DoctorCheckResult, check_gcp_cli
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class GCPProvider(BaseProvider):
|
|
13
|
+
"""GCP deployment provider using Cloud Run."""
|
|
14
|
+
|
|
15
|
+
def doctor(self) -> DoctorReport:
|
|
16
|
+
"""Run GCP-specific health checks."""
|
|
17
|
+
checks = [check_gcp_cli()]
|
|
18
|
+
|
|
19
|
+
# Check if Cloud Run API is enabled
|
|
20
|
+
if self.config.project_id:
|
|
21
|
+
try:
|
|
22
|
+
result = subprocess.run(
|
|
23
|
+
['gcloud', 'services', 'list',
|
|
24
|
+
'--enabled',
|
|
25
|
+
'--filter', 'name:run.googleapis.com',
|
|
26
|
+
'--project', self.config.project_id,
|
|
27
|
+
'--format', 'json'],
|
|
28
|
+
capture_output=True,
|
|
29
|
+
text=True,
|
|
30
|
+
timeout=10
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
if result.returncode == 0:
|
|
34
|
+
services = json.loads(result.stdout)
|
|
35
|
+
if services:
|
|
36
|
+
checks.append(DoctorCheckResult(
|
|
37
|
+
name="Cloud Run API",
|
|
38
|
+
passed=True,
|
|
39
|
+
message="Cloud Run API is enabled"
|
|
40
|
+
))
|
|
41
|
+
else:
|
|
42
|
+
checks.append(DoctorCheckResult(
|
|
43
|
+
name="Cloud Run API",
|
|
44
|
+
passed=False,
|
|
45
|
+
message="Cloud Run API is not enabled",
|
|
46
|
+
fix_suggestion=f"Run: gcloud services enable run.googleapis.com --project={self.config.project_id}"
|
|
47
|
+
))
|
|
48
|
+
except Exception as e:
|
|
49
|
+
checks.append(DoctorCheckResult(
|
|
50
|
+
name="Cloud Run API",
|
|
51
|
+
passed=False,
|
|
52
|
+
message=f"Failed to check Cloud Run API: {e}",
|
|
53
|
+
fix_suggestion="Check gcloud configuration"
|
|
54
|
+
))
|
|
55
|
+
|
|
56
|
+
return DoctorReport(checks=checks)
|
|
57
|
+
|
|
58
|
+
def plan(self) -> Dict[str, Any]:
|
|
59
|
+
"""Generate GCP deployment plan."""
|
|
60
|
+
plan = {
|
|
61
|
+
"provider": "gcp",
|
|
62
|
+
"service_name": self.config.service_name,
|
|
63
|
+
"region": self.config.region,
|
|
64
|
+
"project_id": self.config.project_id,
|
|
65
|
+
"cpu": self.config.cpu,
|
|
66
|
+
"memory": f"{self.config.memory}Mi",
|
|
67
|
+
"min_instances": self.config.min_instances,
|
|
68
|
+
"max_instances": self.config.max_instances,
|
|
69
|
+
"image": self.config.image or f"gcr.io/{self.config.project_id}/{self.config.service_name}:latest",
|
|
70
|
+
"steps": [
|
|
71
|
+
"1. Enable Cloud Run API (if not enabled)",
|
|
72
|
+
"2. Deploy service to Cloud Run",
|
|
73
|
+
"3. Set IAM policy for public access (optional)",
|
|
74
|
+
"4. Get service URL"
|
|
75
|
+
]
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return plan
|
|
79
|
+
|
|
80
|
+
def deploy(self) -> DeployResult:
|
|
81
|
+
"""Deploy to GCP Cloud Run."""
|
|
82
|
+
try:
|
|
83
|
+
if not self.config.project_id:
|
|
84
|
+
return DeployResult(
|
|
85
|
+
success=False,
|
|
86
|
+
message="Project ID is required for GCP deployment",
|
|
87
|
+
error="Please specify project_id in cloud config"
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
# Step 1: Enable Cloud Run API
|
|
91
|
+
print(f"🔧 Enabling Cloud Run API")
|
|
92
|
+
try:
|
|
93
|
+
subprocess.run(
|
|
94
|
+
['gcloud', 'services', 'enable', 'run.googleapis.com',
|
|
95
|
+
'--project', self.config.project_id],
|
|
96
|
+
capture_output=True,
|
|
97
|
+
timeout=60
|
|
98
|
+
)
|
|
99
|
+
except Exception:
|
|
100
|
+
pass # May already be enabled
|
|
101
|
+
|
|
102
|
+
# Step 2: Deploy to Cloud Run
|
|
103
|
+
print(f"🚀 Deploying to Cloud Run: {self.config.service_name}")
|
|
104
|
+
|
|
105
|
+
cmd = [
|
|
106
|
+
'gcloud', 'run', 'deploy', self.config.service_name,
|
|
107
|
+
'--image', self.config.image or f"gcr.io/{self.config.project_id}/{self.config.service_name}:latest",
|
|
108
|
+
'--platform', 'managed',
|
|
109
|
+
'--region', self.config.region,
|
|
110
|
+
'--project', self.config.project_id,
|
|
111
|
+
'--cpu', str(self.config.cpu),
|
|
112
|
+
'--memory', f"{self.config.memory}Mi",
|
|
113
|
+
'--min-instances', str(self.config.min_instances),
|
|
114
|
+
'--max-instances', str(self.config.max_instances),
|
|
115
|
+
'--port', '8005',
|
|
116
|
+
'--allow-unauthenticated'
|
|
117
|
+
]
|
|
118
|
+
|
|
119
|
+
# Add environment variables
|
|
120
|
+
if self.config.env_vars:
|
|
121
|
+
env_str = ','.join([f"{k}={v}" for k, v in self.config.env_vars.items()])
|
|
122
|
+
cmd.extend(['--set-env-vars', env_str])
|
|
123
|
+
|
|
124
|
+
result = subprocess.run(
|
|
125
|
+
cmd,
|
|
126
|
+
capture_output=True,
|
|
127
|
+
text=True,
|
|
128
|
+
timeout=180
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
if result.returncode == 0:
|
|
132
|
+
# Extract URL from output
|
|
133
|
+
try:
|
|
134
|
+
show_result = subprocess.run(
|
|
135
|
+
['gcloud', 'run', 'services', 'describe',
|
|
136
|
+
self.config.service_name,
|
|
137
|
+
'--platform', 'managed',
|
|
138
|
+
'--region', self.config.region,
|
|
139
|
+
'--project', self.config.project_id,
|
|
140
|
+
'--format', 'json'],
|
|
141
|
+
capture_output=True,
|
|
142
|
+
text=True,
|
|
143
|
+
timeout=30
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
if show_result.returncode == 0:
|
|
147
|
+
service_data = json.loads(show_result.stdout)
|
|
148
|
+
url = service_data.get('status', {}).get('url')
|
|
149
|
+
else:
|
|
150
|
+
url = None
|
|
151
|
+
except Exception:
|
|
152
|
+
url = None
|
|
153
|
+
|
|
154
|
+
return DeployResult(
|
|
155
|
+
success=True,
|
|
156
|
+
message=f"Service deployed successfully to Cloud Run",
|
|
157
|
+
url=url,
|
|
158
|
+
metadata={
|
|
159
|
+
"project_id": self.config.project_id,
|
|
160
|
+
"service_name": self.config.service_name,
|
|
161
|
+
"region": self.config.region
|
|
162
|
+
}
|
|
163
|
+
)
|
|
164
|
+
else:
|
|
165
|
+
return DeployResult(
|
|
166
|
+
success=False,
|
|
167
|
+
message="Failed to deploy to Cloud Run",
|
|
168
|
+
error=result.stderr
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
except Exception as e:
|
|
172
|
+
return DeployResult(
|
|
173
|
+
success=False,
|
|
174
|
+
message="GCP deployment failed",
|
|
175
|
+
error=str(e)
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
def status(self) -> DeployStatus:
|
|
179
|
+
"""Get current GCP Cloud Run service status."""
|
|
180
|
+
try:
|
|
181
|
+
if not self.config.project_id:
|
|
182
|
+
return DeployStatus(
|
|
183
|
+
state=ServiceState.UNKNOWN,
|
|
184
|
+
message="Project ID not configured",
|
|
185
|
+
service_name=self.config.service_name,
|
|
186
|
+
provider="gcp",
|
|
187
|
+
region=self.config.region
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
result = subprocess.run(
|
|
191
|
+
['gcloud', 'run', 'services', 'describe',
|
|
192
|
+
self.config.service_name,
|
|
193
|
+
'--platform', 'managed',
|
|
194
|
+
'--region', self.config.region,
|
|
195
|
+
'--project', self.config.project_id,
|
|
196
|
+
'--format', 'json'],
|
|
197
|
+
capture_output=True,
|
|
198
|
+
text=True,
|
|
199
|
+
timeout=30
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
if result.returncode != 0:
|
|
203
|
+
return DeployStatus(
|
|
204
|
+
state=ServiceState.NOT_FOUND,
|
|
205
|
+
message=f"Service not found: {result.stderr}",
|
|
206
|
+
service_name=self.config.service_name,
|
|
207
|
+
provider="gcp",
|
|
208
|
+
region=self.config.region
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
data = json.loads(result.stdout)
|
|
212
|
+
status_data = data.get('status', {})
|
|
213
|
+
conditions = status_data.get('conditions', [])
|
|
214
|
+
|
|
215
|
+
# Get URL
|
|
216
|
+
url = status_data.get('url')
|
|
217
|
+
|
|
218
|
+
# Parse conditions to determine state
|
|
219
|
+
ready_condition = next((c for c in conditions if c.get('type') == 'Ready'), None)
|
|
220
|
+
|
|
221
|
+
if ready_condition:
|
|
222
|
+
if ready_condition.get('status') == 'True':
|
|
223
|
+
state = ServiceState.RUNNING
|
|
224
|
+
elif ready_condition.get('status') == 'Unknown':
|
|
225
|
+
state = ServiceState.PENDING
|
|
226
|
+
else:
|
|
227
|
+
state = ServiceState.FAILED
|
|
228
|
+
else:
|
|
229
|
+
state = ServiceState.UNKNOWN
|
|
230
|
+
|
|
231
|
+
# Get metadata
|
|
232
|
+
metadata_info = data.get('metadata', {})
|
|
233
|
+
spec = data.get('spec', {})
|
|
234
|
+
template = spec.get('template', {})
|
|
235
|
+
|
|
236
|
+
return DeployStatus(
|
|
237
|
+
state=state,
|
|
238
|
+
url=url,
|
|
239
|
+
message=f"Ready: {ready_condition.get('status', 'Unknown') if ready_condition else 'Unknown'}",
|
|
240
|
+
service_name=self.config.service_name,
|
|
241
|
+
provider="gcp",
|
|
242
|
+
region=self.config.region,
|
|
243
|
+
healthy=state == ServiceState.RUNNING,
|
|
244
|
+
instances_running=1 if state == ServiceState.RUNNING else 0,
|
|
245
|
+
instances_desired=1,
|
|
246
|
+
created_at=metadata_info.get('creationTimestamp'),
|
|
247
|
+
metadata={
|
|
248
|
+
"project_id": self.config.project_id,
|
|
249
|
+
"generation": metadata_info.get('generation'),
|
|
250
|
+
"latest_revision": status_data.get('latestReadyRevisionName'),
|
|
251
|
+
"traffic": status_data.get('traffic', [])
|
|
252
|
+
}
|
|
253
|
+
)
|
|
254
|
+
|
|
255
|
+
except Exception as e:
|
|
256
|
+
return DeployStatus(
|
|
257
|
+
state=ServiceState.UNKNOWN,
|
|
258
|
+
message=f"Failed to get status: {e}",
|
|
259
|
+
service_name=self.config.service_name,
|
|
260
|
+
provider="gcp",
|
|
261
|
+
region=self.config.region
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
def destroy(self, force: bool = False) -> DestroyResult:
|
|
265
|
+
"""Destroy GCP Cloud Run service."""
|
|
266
|
+
try:
|
|
267
|
+
if not self.config.project_id:
|
|
268
|
+
return DestroyResult(
|
|
269
|
+
success=False,
|
|
270
|
+
message="Project ID not configured",
|
|
271
|
+
error="Please specify project_id in cloud config"
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
deleted_resources = []
|
|
275
|
+
|
|
276
|
+
# Delete the Cloud Run service
|
|
277
|
+
print(f"🗑️ Deleting Cloud Run service: {self.config.service_name}")
|
|
278
|
+
result = subprocess.run(
|
|
279
|
+
['gcloud', 'run', 'services', 'delete',
|
|
280
|
+
self.config.service_name,
|
|
281
|
+
'--platform', 'managed',
|
|
282
|
+
'--region', self.config.region,
|
|
283
|
+
'--project', self.config.project_id,
|
|
284
|
+
'--quiet'],
|
|
285
|
+
capture_output=True,
|
|
286
|
+
text=True,
|
|
287
|
+
timeout=120
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
if result.returncode == 0:
|
|
291
|
+
deleted_resources.append(f"cloud-run:{self.config.service_name}")
|
|
292
|
+
return DestroyResult(
|
|
293
|
+
success=True,
|
|
294
|
+
message="Successfully destroyed GCP Cloud Run service",
|
|
295
|
+
resources_deleted=deleted_resources,
|
|
296
|
+
metadata={
|
|
297
|
+
"project_id": self.config.project_id,
|
|
298
|
+
"region": self.config.region
|
|
299
|
+
}
|
|
300
|
+
)
|
|
301
|
+
else:
|
|
302
|
+
return DestroyResult(
|
|
303
|
+
success=False,
|
|
304
|
+
message="Failed to delete Cloud Run service",
|
|
305
|
+
error=result.stderr,
|
|
306
|
+
resources_deleted=deleted_resources
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
except Exception as e:
|
|
310
|
+
return DestroyResult(
|
|
311
|
+
success=False,
|
|
312
|
+
message="Failed to destroy GCP resources",
|
|
313
|
+
error=str(e)
|
|
314
|
+
)
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
"""
|
|
2
|
+
YAML schema validation for deploy configurations.
|
|
3
|
+
"""
|
|
4
|
+
import yaml
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Optional
|
|
7
|
+
from .models import DeployConfig, DeployType, CloudProvider, APIConfig, DockerConfig, CloudConfig
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def validate_agents_yaml(file_path: str) -> Optional[DeployConfig]:
|
|
11
|
+
"""
|
|
12
|
+
Validate agents.yaml file and extract deploy configuration.
|
|
13
|
+
|
|
14
|
+
Args:
|
|
15
|
+
file_path: Path to agents.yaml file
|
|
16
|
+
|
|
17
|
+
Returns:
|
|
18
|
+
DeployConfig if deploy section exists, None otherwise
|
|
19
|
+
|
|
20
|
+
Raises:
|
|
21
|
+
FileNotFoundError: If file doesn't exist
|
|
22
|
+
ValueError: If deploy config is invalid
|
|
23
|
+
"""
|
|
24
|
+
path = Path(file_path)
|
|
25
|
+
if not path.exists():
|
|
26
|
+
raise FileNotFoundError(f"File not found: {file_path}")
|
|
27
|
+
|
|
28
|
+
with open(path, 'r') as f:
|
|
29
|
+
data = yaml.safe_load(f)
|
|
30
|
+
|
|
31
|
+
if not data or 'deploy' not in data:
|
|
32
|
+
return None
|
|
33
|
+
|
|
34
|
+
deploy_data = data['deploy']
|
|
35
|
+
|
|
36
|
+
# Parse deploy type
|
|
37
|
+
deploy_type_str = deploy_data.get('type')
|
|
38
|
+
if not deploy_type_str:
|
|
39
|
+
raise ValueError("Deploy type is required")
|
|
40
|
+
|
|
41
|
+
try:
|
|
42
|
+
deploy_type = DeployType(deploy_type_str)
|
|
43
|
+
except ValueError:
|
|
44
|
+
raise ValueError(f"Invalid deploy type: {deploy_type_str}. Must be one of: api, docker, cloud")
|
|
45
|
+
|
|
46
|
+
# Build config based on type
|
|
47
|
+
config_dict = {'type': deploy_type}
|
|
48
|
+
|
|
49
|
+
if deploy_type == DeployType.API:
|
|
50
|
+
api_data = deploy_data.get('api', {})
|
|
51
|
+
config_dict['api'] = APIConfig(**api_data) if api_data else APIConfig()
|
|
52
|
+
|
|
53
|
+
elif deploy_type == DeployType.DOCKER:
|
|
54
|
+
docker_data = deploy_data.get('docker', {})
|
|
55
|
+
config_dict['docker'] = DockerConfig(**docker_data) if docker_data else DockerConfig()
|
|
56
|
+
|
|
57
|
+
elif deploy_type == DeployType.CLOUD:
|
|
58
|
+
cloud_data = deploy_data.get('cloud', {})
|
|
59
|
+
if not cloud_data:
|
|
60
|
+
raise ValueError("Cloud configuration is required for cloud deployment type")
|
|
61
|
+
|
|
62
|
+
# Parse provider
|
|
63
|
+
provider_str = cloud_data.get('provider')
|
|
64
|
+
if not provider_str:
|
|
65
|
+
raise ValueError("Cloud provider is required")
|
|
66
|
+
|
|
67
|
+
try:
|
|
68
|
+
cloud_data['provider'] = CloudProvider(provider_str)
|
|
69
|
+
except ValueError:
|
|
70
|
+
raise ValueError(f"Invalid cloud provider: {provider_str}. Must be one of: aws, azure, gcp")
|
|
71
|
+
|
|
72
|
+
config_dict['cloud'] = CloudConfig(**cloud_data)
|
|
73
|
+
|
|
74
|
+
# Parse agents if present
|
|
75
|
+
if 'agents' in deploy_data:
|
|
76
|
+
config_dict['agents'] = deploy_data['agents']
|
|
77
|
+
|
|
78
|
+
return DeployConfig(**config_dict)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def generate_sample_yaml(deploy_type: DeployType, provider: Optional[CloudProvider] = None) -> str:
|
|
82
|
+
"""
|
|
83
|
+
Generate sample agents.yaml with deploy configuration.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
deploy_type: Type of deployment
|
|
87
|
+
provider: Cloud provider (required if deploy_type is CLOUD)
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
YAML string with sample configuration
|
|
91
|
+
"""
|
|
92
|
+
base_yaml = """name: Sample Agent
|
|
93
|
+
description: Sample agent configuration with deploy settings
|
|
94
|
+
framework: praisonai
|
|
95
|
+
|
|
96
|
+
agents:
|
|
97
|
+
assistant:
|
|
98
|
+
name: Assistant
|
|
99
|
+
role: Helper
|
|
100
|
+
goal: Help users with tasks
|
|
101
|
+
backstory: Experienced assistant ready to help
|
|
102
|
+
instructions: |
|
|
103
|
+
Provide helpful responses to user queries.
|
|
104
|
+
Be concise and accurate.
|
|
105
|
+
|
|
106
|
+
"""
|
|
107
|
+
|
|
108
|
+
if deploy_type == DeployType.API:
|
|
109
|
+
deploy_yaml = """deploy:
|
|
110
|
+
type: api
|
|
111
|
+
api:
|
|
112
|
+
host: 0.0.0.0
|
|
113
|
+
port: 8005
|
|
114
|
+
workers: 1
|
|
115
|
+
cors_enabled: true
|
|
116
|
+
auth_enabled: false
|
|
117
|
+
"""
|
|
118
|
+
|
|
119
|
+
elif deploy_type == DeployType.DOCKER:
|
|
120
|
+
deploy_yaml = """deploy:
|
|
121
|
+
type: docker
|
|
122
|
+
docker:
|
|
123
|
+
image_name: praisonai-app
|
|
124
|
+
tag: latest
|
|
125
|
+
base_image: python:3.11-slim
|
|
126
|
+
expose:
|
|
127
|
+
- 8005
|
|
128
|
+
registry: null
|
|
129
|
+
push: false
|
|
130
|
+
"""
|
|
131
|
+
|
|
132
|
+
elif deploy_type == DeployType.CLOUD:
|
|
133
|
+
if provider == CloudProvider.AWS:
|
|
134
|
+
deploy_yaml = """deploy:
|
|
135
|
+
type: cloud
|
|
136
|
+
cloud:
|
|
137
|
+
provider: aws
|
|
138
|
+
region: us-east-1
|
|
139
|
+
service_name: praisonai-service
|
|
140
|
+
cpu: "256"
|
|
141
|
+
memory: "512"
|
|
142
|
+
min_instances: 1
|
|
143
|
+
max_instances: 10
|
|
144
|
+
# image: your-registry/praisonai-app:latest
|
|
145
|
+
# cluster_name: praisonai-cluster
|
|
146
|
+
"""
|
|
147
|
+
|
|
148
|
+
elif provider == CloudProvider.AZURE:
|
|
149
|
+
deploy_yaml = """deploy:
|
|
150
|
+
type: cloud
|
|
151
|
+
cloud:
|
|
152
|
+
provider: azure
|
|
153
|
+
region: eastus
|
|
154
|
+
service_name: praisonai-service
|
|
155
|
+
resource_group: praisonai-rg
|
|
156
|
+
subscription_id: your-subscription-id
|
|
157
|
+
cpu: "0.5"
|
|
158
|
+
memory: "1.0"
|
|
159
|
+
min_instances: 1
|
|
160
|
+
max_instances: 10
|
|
161
|
+
# image: your-registry.azurecr.io/praisonai-app:latest
|
|
162
|
+
"""
|
|
163
|
+
|
|
164
|
+
elif provider == CloudProvider.GCP:
|
|
165
|
+
deploy_yaml = """deploy:
|
|
166
|
+
type: cloud
|
|
167
|
+
cloud:
|
|
168
|
+
provider: gcp
|
|
169
|
+
region: us-central1
|
|
170
|
+
service_name: praisonai-service
|
|
171
|
+
project_id: your-project-id
|
|
172
|
+
cpu: "1"
|
|
173
|
+
memory: "512"
|
|
174
|
+
min_instances: 1
|
|
175
|
+
max_instances: 10
|
|
176
|
+
# image: gcr.io/your-project-id/praisonai-app:latest
|
|
177
|
+
"""
|
|
178
|
+
else:
|
|
179
|
+
deploy_yaml = """deploy:
|
|
180
|
+
type: cloud
|
|
181
|
+
cloud:
|
|
182
|
+
provider: aws # or azure, gcp
|
|
183
|
+
region: us-east-1
|
|
184
|
+
service_name: praisonai-service
|
|
185
|
+
"""
|
|
186
|
+
|
|
187
|
+
else:
|
|
188
|
+
deploy_yaml = ""
|
|
189
|
+
|
|
190
|
+
return base_yaml + deploy_yaml
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def save_sample_yaml(file_path: str, deploy_type: DeployType, provider: Optional[CloudProvider] = None):
|
|
194
|
+
"""
|
|
195
|
+
Save sample agents.yaml to file.
|
|
196
|
+
|
|
197
|
+
Args:
|
|
198
|
+
file_path: Path to save the file
|
|
199
|
+
deploy_type: Type of deployment
|
|
200
|
+
provider: Cloud provider (required if deploy_type is CLOUD)
|
|
201
|
+
"""
|
|
202
|
+
yaml_content = generate_sample_yaml(deploy_type, provider)
|
|
203
|
+
|
|
204
|
+
path = Path(file_path)
|
|
205
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
206
|
+
|
|
207
|
+
with open(path, 'w') as f:
|
|
208
|
+
f.write(yaml_content)
|