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,511 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Debug and Simulation CLI Commands for PraisonAI TUI.
|
|
3
|
+
|
|
4
|
+
Provides headless TUI simulation, tracing, and debugging capabilities.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import asyncio
|
|
8
|
+
import json
|
|
9
|
+
import sys
|
|
10
|
+
import time
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from typing import Any, Dict, List, Optional
|
|
13
|
+
|
|
14
|
+
try:
|
|
15
|
+
import typer
|
|
16
|
+
from rich.console import Console
|
|
17
|
+
from rich.table import Table
|
|
18
|
+
from rich.panel import Panel
|
|
19
|
+
from rich.live import Live
|
|
20
|
+
from rich.text import Text
|
|
21
|
+
TYPER_AVAILABLE = True
|
|
22
|
+
except ImportError:
|
|
23
|
+
TYPER_AVAILABLE = False
|
|
24
|
+
typer = None
|
|
25
|
+
|
|
26
|
+
console = Console() if TYPER_AVAILABLE else None
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def create_debug_app():
|
|
30
|
+
"""Create the debug CLI app with simulation commands."""
|
|
31
|
+
if not TYPER_AVAILABLE:
|
|
32
|
+
return None
|
|
33
|
+
|
|
34
|
+
app = typer.Typer(
|
|
35
|
+
name="tui",
|
|
36
|
+
help="TUI and simulation commands",
|
|
37
|
+
no_args_is_help=True,
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
@app.command("launch")
|
|
41
|
+
def tui_launch(
|
|
42
|
+
workspace: Optional[str] = typer.Option(None, "--workspace", "-w"),
|
|
43
|
+
session: Optional[str] = typer.Option(None, "--session", "-s"),
|
|
44
|
+
model: Optional[str] = typer.Option(None, "--model", "-m"),
|
|
45
|
+
debug: bool = typer.Option(False, "--debug", "-d", help="Enable debug overlays"),
|
|
46
|
+
log_jsonl: Optional[str] = typer.Option(None, "--log-jsonl", help="Write events to JSONL file"),
|
|
47
|
+
profile: bool = typer.Option(False, "--profile", help="Enable performance profiling"),
|
|
48
|
+
):
|
|
49
|
+
"""Launch the interactive TUI."""
|
|
50
|
+
try:
|
|
51
|
+
from .app import run_tui
|
|
52
|
+
except ImportError:
|
|
53
|
+
console.print("[red]Textual is required for TUI. Install with:[/red]\n pip install praisonai[tui]")
|
|
54
|
+
raise typer.Exit(1)
|
|
55
|
+
|
|
56
|
+
# Set debug environment
|
|
57
|
+
if debug:
|
|
58
|
+
import os
|
|
59
|
+
os.environ["PRAISONAI_TUI_DEBUG"] = "1"
|
|
60
|
+
|
|
61
|
+
if log_jsonl:
|
|
62
|
+
import os
|
|
63
|
+
os.environ["PRAISONAI_TUI_JSONL"] = log_jsonl
|
|
64
|
+
|
|
65
|
+
run_tui(workspace=workspace, session_id=session, model=model)
|
|
66
|
+
|
|
67
|
+
@app.command("simulate")
|
|
68
|
+
def tui_simulate(
|
|
69
|
+
script: str = typer.Argument(..., help="Path to simulation script (YAML/JSON)"),
|
|
70
|
+
mock: bool = typer.Option(True, "--mock/--real-llm", help="Use mock provider"),
|
|
71
|
+
pretty: bool = typer.Option(True, "--pretty/--jsonl", help="Output format"),
|
|
72
|
+
assert_mode: bool = typer.Option(False, "--assert", help="Validate expected outcomes"),
|
|
73
|
+
timeout: float = typer.Option(60.0, "--timeout", help="Max execution time"),
|
|
74
|
+
):
|
|
75
|
+
"""Run a headless TUI simulation script."""
|
|
76
|
+
import os
|
|
77
|
+
|
|
78
|
+
# Safety gate for real LLM
|
|
79
|
+
if not mock:
|
|
80
|
+
if not os.environ.get("PRAISONAI_REAL_LLM"):
|
|
81
|
+
console.print("[red]Real LLM mode requires PRAISONAI_REAL_LLM=1 environment variable[/red]")
|
|
82
|
+
raise typer.Exit(1)
|
|
83
|
+
|
|
84
|
+
# Load script
|
|
85
|
+
script_path = Path(script)
|
|
86
|
+
if not script_path.exists():
|
|
87
|
+
console.print(f"[red]Script not found: {script}[/red]")
|
|
88
|
+
raise typer.Exit(1)
|
|
89
|
+
|
|
90
|
+
with open(script_path) as f:
|
|
91
|
+
if script_path.suffix in (".yaml", ".yml"):
|
|
92
|
+
import yaml
|
|
93
|
+
script_data = yaml.safe_load(f)
|
|
94
|
+
else:
|
|
95
|
+
script_data = json.load(f)
|
|
96
|
+
|
|
97
|
+
# Run simulation
|
|
98
|
+
from .orchestrator import TuiOrchestrator, SimulationRunner, OutputMode
|
|
99
|
+
from ..queue import QueueConfig
|
|
100
|
+
|
|
101
|
+
output_mode = OutputMode.PRETTY if pretty else OutputMode.JSONL
|
|
102
|
+
|
|
103
|
+
config = QueueConfig(enable_persistence=not mock)
|
|
104
|
+
orchestrator = TuiOrchestrator(
|
|
105
|
+
queue_config=config,
|
|
106
|
+
output_mode=output_mode,
|
|
107
|
+
debug=True,
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
runner = SimulationRunner(orchestrator, assert_mode=assert_mode)
|
|
111
|
+
|
|
112
|
+
async def run():
|
|
113
|
+
return await asyncio.wait_for(
|
|
114
|
+
runner.run_script(script_data),
|
|
115
|
+
timeout=timeout
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
try:
|
|
119
|
+
success = asyncio.run(run())
|
|
120
|
+
except asyncio.TimeoutError:
|
|
121
|
+
console.print(f"[red]Simulation timed out after {timeout}s[/red]")
|
|
122
|
+
raise typer.Exit(1)
|
|
123
|
+
|
|
124
|
+
# Print summary
|
|
125
|
+
summary = runner.get_summary()
|
|
126
|
+
if assert_mode:
|
|
127
|
+
console.print(Panel(
|
|
128
|
+
f"Passed: {summary['assertions_passed']}\n"
|
|
129
|
+
f"Failed: {summary['assertions_failed']}\n"
|
|
130
|
+
f"Errors: {len(summary['errors'])}",
|
|
131
|
+
title="Simulation Results"
|
|
132
|
+
))
|
|
133
|
+
|
|
134
|
+
if summary['errors']:
|
|
135
|
+
for error in summary['errors']:
|
|
136
|
+
console.print(f"[red] ✗ {error}[/red]")
|
|
137
|
+
|
|
138
|
+
if not success:
|
|
139
|
+
raise typer.Exit(1)
|
|
140
|
+
|
|
141
|
+
@app.command("snapshot")
|
|
142
|
+
def tui_snapshot(
|
|
143
|
+
session: Optional[str] = typer.Option(None, "--session", "-s"),
|
|
144
|
+
run_id: Optional[str] = typer.Option(None, "--run", "-r"),
|
|
145
|
+
json_output: bool = typer.Option(False, "--json", "-j"),
|
|
146
|
+
):
|
|
147
|
+
"""Print a TUI-like snapshot of current state."""
|
|
148
|
+
from ..queue import QueuePersistence, RunState
|
|
149
|
+
|
|
150
|
+
persistence = QueuePersistence()
|
|
151
|
+
persistence.initialize()
|
|
152
|
+
|
|
153
|
+
# Build snapshot
|
|
154
|
+
snapshot = {
|
|
155
|
+
"timestamp": time.time(),
|
|
156
|
+
"session_id": session,
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
# Get runs
|
|
160
|
+
runs = persistence.list_runs(session_id=session, limit=100)
|
|
161
|
+
|
|
162
|
+
queued = [r for r in runs if r.state == RunState.QUEUED]
|
|
163
|
+
running = [r for r in runs if r.state == RunState.RUNNING]
|
|
164
|
+
recent = [r for r in runs if r.state.is_terminal()][-5:]
|
|
165
|
+
|
|
166
|
+
snapshot["queued_count"] = len(queued)
|
|
167
|
+
snapshot["running_count"] = len(running)
|
|
168
|
+
snapshot["recent_runs"] = [
|
|
169
|
+
{
|
|
170
|
+
"run_id": r.run_id[:8],
|
|
171
|
+
"agent": r.agent_name,
|
|
172
|
+
"state": r.state.value,
|
|
173
|
+
"input": r.input_content[:50],
|
|
174
|
+
}
|
|
175
|
+
for r in recent
|
|
176
|
+
]
|
|
177
|
+
|
|
178
|
+
# Get specific run if requested
|
|
179
|
+
if run_id:
|
|
180
|
+
run = persistence.load_run(run_id)
|
|
181
|
+
if run:
|
|
182
|
+
snapshot["run"] = run.to_dict()
|
|
183
|
+
|
|
184
|
+
# Get session info
|
|
185
|
+
if session:
|
|
186
|
+
session_data = persistence.load_session(session)
|
|
187
|
+
if session_data:
|
|
188
|
+
snapshot["session"] = session_data
|
|
189
|
+
|
|
190
|
+
persistence.close()
|
|
191
|
+
|
|
192
|
+
if json_output:
|
|
193
|
+
console.print(json.dumps(snapshot, indent=2, default=str))
|
|
194
|
+
else:
|
|
195
|
+
# Pretty print
|
|
196
|
+
console.print("─" * 60)
|
|
197
|
+
console.print(f"◉ PraisonAI Snapshot │ {time.strftime('%Y-%m-%d %H:%M:%S')}")
|
|
198
|
+
console.print("─" * 60)
|
|
199
|
+
|
|
200
|
+
console.print(f"\n[bold]Queue Status[/bold]")
|
|
201
|
+
console.print(f" Queued: {snapshot['queued_count']} │ Running: {snapshot['running_count']}")
|
|
202
|
+
|
|
203
|
+
if snapshot["recent_runs"]:
|
|
204
|
+
console.print(f"\n[bold]Recent Runs[/bold]")
|
|
205
|
+
for r in snapshot["recent_runs"]:
|
|
206
|
+
state_color = {
|
|
207
|
+
"succeeded": "green",
|
|
208
|
+
"failed": "red",
|
|
209
|
+
"cancelled": "dim",
|
|
210
|
+
}.get(r["state"], "yellow")
|
|
211
|
+
console.print(f" [{state_color}]{r['run_id']}[/{state_color}] {r['agent']}: {r['input'][:30]}...")
|
|
212
|
+
|
|
213
|
+
if "run" in snapshot:
|
|
214
|
+
console.print(f"\n[bold]Run Details[/bold]")
|
|
215
|
+
run = snapshot["run"]
|
|
216
|
+
console.print(f" ID: {run.get('run_id', 'N/A')}")
|
|
217
|
+
console.print(f" State: {run.get('state', 'N/A')}")
|
|
218
|
+
console.print(f" Agent: {run.get('agent_name', 'N/A')}")
|
|
219
|
+
|
|
220
|
+
console.print("─" * 60)
|
|
221
|
+
|
|
222
|
+
@app.command("trace")
|
|
223
|
+
def tui_trace(
|
|
224
|
+
id: str = typer.Argument(..., help="Session or run ID to trace"),
|
|
225
|
+
follow: bool = typer.Option(False, "--follow", "-f", help="Follow new events"),
|
|
226
|
+
limit: int = typer.Option(50, "--limit", "-n", help="Max events to show"),
|
|
227
|
+
):
|
|
228
|
+
"""Replay events from persistence like a timeline."""
|
|
229
|
+
from ..queue import QueuePersistence
|
|
230
|
+
|
|
231
|
+
persistence = QueuePersistence()
|
|
232
|
+
persistence.initialize()
|
|
233
|
+
|
|
234
|
+
# Try to find as session or run
|
|
235
|
+
session = persistence.load_session(id)
|
|
236
|
+
run = persistence.load_run(id)
|
|
237
|
+
|
|
238
|
+
if not session and not run:
|
|
239
|
+
# Try partial match
|
|
240
|
+
runs = persistence.list_runs(limit=100)
|
|
241
|
+
matches = [r for r in runs if r.run_id.startswith(id) or r.session_id.startswith(id)]
|
|
242
|
+
if matches:
|
|
243
|
+
run = matches[0]
|
|
244
|
+
|
|
245
|
+
if not session and not run:
|
|
246
|
+
console.print(f"[red]No session or run found for: {id}[/red]")
|
|
247
|
+
persistence.close()
|
|
248
|
+
raise typer.Exit(1)
|
|
249
|
+
|
|
250
|
+
# Get runs for timeline
|
|
251
|
+
if session:
|
|
252
|
+
runs = persistence.list_runs(session_id=id, limit=limit)
|
|
253
|
+
else:
|
|
254
|
+
runs = [run] if run else []
|
|
255
|
+
|
|
256
|
+
# Build timeline
|
|
257
|
+
events = []
|
|
258
|
+
for r in runs:
|
|
259
|
+
events.append({
|
|
260
|
+
"timestamp": r.created_at,
|
|
261
|
+
"type": "run_created",
|
|
262
|
+
"run_id": r.run_id[:8],
|
|
263
|
+
"agent": r.agent_name,
|
|
264
|
+
"input": r.input_content[:50],
|
|
265
|
+
})
|
|
266
|
+
if r.started_at:
|
|
267
|
+
events.append({
|
|
268
|
+
"timestamp": r.started_at,
|
|
269
|
+
"type": "run_started",
|
|
270
|
+
"run_id": r.run_id[:8],
|
|
271
|
+
})
|
|
272
|
+
if r.ended_at:
|
|
273
|
+
events.append({
|
|
274
|
+
"timestamp": r.ended_at,
|
|
275
|
+
"type": f"run_{r.state.value}",
|
|
276
|
+
"run_id": r.run_id[:8],
|
|
277
|
+
})
|
|
278
|
+
|
|
279
|
+
# Sort by timestamp
|
|
280
|
+
events.sort(key=lambda e: e["timestamp"])
|
|
281
|
+
|
|
282
|
+
persistence.close()
|
|
283
|
+
|
|
284
|
+
# Print timeline
|
|
285
|
+
console.print(f"\n[bold]Event Timeline for {id[:8]}[/bold]\n")
|
|
286
|
+
|
|
287
|
+
for event in events[-limit:]:
|
|
288
|
+
ts = time.strftime("%H:%M:%S", time.localtime(event["timestamp"]))
|
|
289
|
+
event_type = event["type"]
|
|
290
|
+
|
|
291
|
+
type_colors = {
|
|
292
|
+
"run_created": "cyan",
|
|
293
|
+
"run_started": "yellow",
|
|
294
|
+
"run_succeeded": "green",
|
|
295
|
+
"run_failed": "red",
|
|
296
|
+
"run_cancelled": "dim",
|
|
297
|
+
}
|
|
298
|
+
color = type_colors.get(event_type, "white")
|
|
299
|
+
|
|
300
|
+
line = f"[dim]{ts}[/dim] [{color}]{event_type:15}[/{color}]"
|
|
301
|
+
if "run_id" in event:
|
|
302
|
+
line += f" run={event['run_id']}"
|
|
303
|
+
if "agent" in event:
|
|
304
|
+
line += f" agent={event['agent']}"
|
|
305
|
+
if "input" in event:
|
|
306
|
+
line += f" \"{event['input']}...\""
|
|
307
|
+
|
|
308
|
+
console.print(line)
|
|
309
|
+
|
|
310
|
+
if follow:
|
|
311
|
+
console.print("\n[dim]Following... (Ctrl+C to stop)[/dim]")
|
|
312
|
+
# In a real implementation, this would poll for new events
|
|
313
|
+
|
|
314
|
+
return app
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
def create_queue_watch_command():
|
|
318
|
+
"""Create the queue watch command."""
|
|
319
|
+
if not TYPER_AVAILABLE:
|
|
320
|
+
return None
|
|
321
|
+
|
|
322
|
+
def queue_watch(
|
|
323
|
+
state: Optional[str] = typer.Option(None, "--state", "-s"),
|
|
324
|
+
agent: Optional[str] = typer.Option(None, "--agent", "-a"),
|
|
325
|
+
run_id: Optional[str] = typer.Option(None, "--run", "-r"),
|
|
326
|
+
jsonl: bool = typer.Option(False, "--jsonl", "-j"),
|
|
327
|
+
interval: float = typer.Option(1.0, "--interval", "-i"),
|
|
328
|
+
):
|
|
329
|
+
"""Watch queue events in real time."""
|
|
330
|
+
from ..queue import QueuePersistence, RunState
|
|
331
|
+
|
|
332
|
+
persistence = QueuePersistence()
|
|
333
|
+
persistence.initialize()
|
|
334
|
+
|
|
335
|
+
last_seen = {}
|
|
336
|
+
|
|
337
|
+
try:
|
|
338
|
+
while True:
|
|
339
|
+
runs = persistence.list_runs(limit=100)
|
|
340
|
+
|
|
341
|
+
# Filter
|
|
342
|
+
if state:
|
|
343
|
+
try:
|
|
344
|
+
state_filter = RunState(state.lower())
|
|
345
|
+
runs = [r for r in runs if r.state == state_filter]
|
|
346
|
+
except ValueError:
|
|
347
|
+
pass
|
|
348
|
+
|
|
349
|
+
if agent:
|
|
350
|
+
runs = [r for r in runs if agent.lower() in r.agent_name.lower()]
|
|
351
|
+
|
|
352
|
+
if run_id:
|
|
353
|
+
runs = [r for r in runs if r.run_id.startswith(run_id)]
|
|
354
|
+
|
|
355
|
+
# Check for changes
|
|
356
|
+
for run in runs:
|
|
357
|
+
key = run.run_id
|
|
358
|
+
current_state = run.state.value
|
|
359
|
+
|
|
360
|
+
if key not in last_seen or last_seen[key] != current_state:
|
|
361
|
+
last_seen[key] = current_state
|
|
362
|
+
|
|
363
|
+
if jsonl:
|
|
364
|
+
event = {
|
|
365
|
+
"timestamp": time.time(),
|
|
366
|
+
"run_id": run.run_id,
|
|
367
|
+
"agent": run.agent_name,
|
|
368
|
+
"state": current_state,
|
|
369
|
+
}
|
|
370
|
+
print(json.dumps(event))
|
|
371
|
+
else:
|
|
372
|
+
ts = time.strftime("%H:%M:%S")
|
|
373
|
+
state_colors = {
|
|
374
|
+
"queued": "yellow",
|
|
375
|
+
"running": "cyan",
|
|
376
|
+
"succeeded": "green",
|
|
377
|
+
"failed": "red",
|
|
378
|
+
"cancelled": "dim",
|
|
379
|
+
}
|
|
380
|
+
color = state_colors.get(current_state, "white")
|
|
381
|
+
console.print(
|
|
382
|
+
f"[dim]{ts}[/dim] [{color}]{current_state:10}[/{color}] "
|
|
383
|
+
f"{run.run_id[:8]} {run.agent_name}"
|
|
384
|
+
)
|
|
385
|
+
|
|
386
|
+
time.sleep(interval)
|
|
387
|
+
|
|
388
|
+
except KeyboardInterrupt:
|
|
389
|
+
console.print("\n[dim]Stopped watching[/dim]")
|
|
390
|
+
finally:
|
|
391
|
+
persistence.close()
|
|
392
|
+
|
|
393
|
+
return queue_watch
|
|
394
|
+
|
|
395
|
+
|
|
396
|
+
def create_doctor_command():
|
|
397
|
+
"""Create the doctor command for TUI diagnostics."""
|
|
398
|
+
if not TYPER_AVAILABLE:
|
|
399
|
+
return None
|
|
400
|
+
|
|
401
|
+
def doctor_tui():
|
|
402
|
+
"""Validate TUI dependencies, DB schema, and wiring."""
|
|
403
|
+
checks = []
|
|
404
|
+
|
|
405
|
+
# Check Textual
|
|
406
|
+
try:
|
|
407
|
+
import textual
|
|
408
|
+
checks.append(("Textual", "✓", f"v{textual.__version__}", "green"))
|
|
409
|
+
except ImportError:
|
|
410
|
+
checks.append(("Textual", "✗", "Not installed", "red"))
|
|
411
|
+
|
|
412
|
+
# Check Rich
|
|
413
|
+
try:
|
|
414
|
+
import rich
|
|
415
|
+
checks.append(("Rich", "✓", f"v{rich.__version__}", "green"))
|
|
416
|
+
except ImportError:
|
|
417
|
+
checks.append(("Rich", "✗", "Not installed", "red"))
|
|
418
|
+
|
|
419
|
+
# Check Typer
|
|
420
|
+
try:
|
|
421
|
+
import typer
|
|
422
|
+
checks.append(("Typer", "✓", f"v{typer.__version__}", "green"))
|
|
423
|
+
except ImportError:
|
|
424
|
+
checks.append(("Typer", "✗", "Not installed", "red"))
|
|
425
|
+
|
|
426
|
+
# Check queue modules
|
|
427
|
+
try:
|
|
428
|
+
from ..queue import QueueManager, QueueScheduler, QueuePersistence
|
|
429
|
+
checks.append(("Queue System", "✓", "All modules loaded", "green"))
|
|
430
|
+
except ImportError as e:
|
|
431
|
+
checks.append(("Queue System", "✗", str(e), "red"))
|
|
432
|
+
|
|
433
|
+
# Check TUI modules
|
|
434
|
+
try:
|
|
435
|
+
from .orchestrator import TuiOrchestrator
|
|
436
|
+
checks.append(("TUI Orchestrator", "✓", "Loaded", "green"))
|
|
437
|
+
except ImportError as e:
|
|
438
|
+
checks.append(("TUI Orchestrator", "✗", str(e), "red"))
|
|
439
|
+
|
|
440
|
+
# Check events
|
|
441
|
+
try:
|
|
442
|
+
from .events import TUIEvent, TUIEventType
|
|
443
|
+
event_count = len(TUIEventType)
|
|
444
|
+
checks.append(("TUI Events", "✓", f"{event_count} event types", "green"))
|
|
445
|
+
except ImportError as e:
|
|
446
|
+
checks.append(("TUI Events", "✗", str(e), "red"))
|
|
447
|
+
|
|
448
|
+
# Check DB
|
|
449
|
+
try:
|
|
450
|
+
from ..queue import QueuePersistence
|
|
451
|
+
p = QueuePersistence()
|
|
452
|
+
p.initialize()
|
|
453
|
+
stats = p.get_stats()
|
|
454
|
+
p.close()
|
|
455
|
+
checks.append(("Database", "✓", f"{stats.total_runs} runs in DB", "green"))
|
|
456
|
+
except Exception as e:
|
|
457
|
+
checks.append(("Database", "✗", str(e), "red"))
|
|
458
|
+
|
|
459
|
+
# Check slash commands
|
|
460
|
+
try:
|
|
461
|
+
from ..slash_commands import SlashCommandRegistry
|
|
462
|
+
registry = SlashCommandRegistry()
|
|
463
|
+
cmd_count = len(registry.commands)
|
|
464
|
+
checks.append(("Slash Commands", "✓", f"{cmd_count} commands", "green"))
|
|
465
|
+
except Exception as e:
|
|
466
|
+
checks.append(("Slash Commands", "⚠", str(e), "yellow"))
|
|
467
|
+
|
|
468
|
+
# Print results
|
|
469
|
+
console.print("\n[bold]PraisonAI TUI Diagnostics[/bold]\n")
|
|
470
|
+
|
|
471
|
+
table = Table(show_header=True)
|
|
472
|
+
table.add_column("Component")
|
|
473
|
+
table.add_column("Status")
|
|
474
|
+
table.add_column("Details")
|
|
475
|
+
|
|
476
|
+
all_ok = True
|
|
477
|
+
for name, status, details, color in checks:
|
|
478
|
+
table.add_row(name, f"[{color}]{status}[/{color}]", details)
|
|
479
|
+
if status == "✗":
|
|
480
|
+
all_ok = False
|
|
481
|
+
|
|
482
|
+
console.print(table)
|
|
483
|
+
|
|
484
|
+
if all_ok:
|
|
485
|
+
console.print("\n[green]All checks passed![/green]")
|
|
486
|
+
else:
|
|
487
|
+
console.print("\n[red]Some checks failed. Run 'pip install praisonai[tui]' to install missing dependencies.[/red]")
|
|
488
|
+
raise typer.Exit(1)
|
|
489
|
+
|
|
490
|
+
return doctor_tui
|
|
491
|
+
|
|
492
|
+
|
|
493
|
+
def register_debug_commands(app):
|
|
494
|
+
"""Register debug commands with the main CLI app."""
|
|
495
|
+
if not TYPER_AVAILABLE:
|
|
496
|
+
return
|
|
497
|
+
|
|
498
|
+
debug_app = create_debug_app()
|
|
499
|
+
watch_cmd = create_queue_watch_command()
|
|
500
|
+
doctor_cmd = create_doctor_command()
|
|
501
|
+
|
|
502
|
+
if debug_app:
|
|
503
|
+
app.add_typer(debug_app, name="tui")
|
|
504
|
+
|
|
505
|
+
if watch_cmd:
|
|
506
|
+
# Add to queue subcommand
|
|
507
|
+
pass # Will be added via queue app
|
|
508
|
+
|
|
509
|
+
if doctor_cmd:
|
|
510
|
+
# Add doctor --tui option
|
|
511
|
+
pass # Will be added via main app
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Custom events for PraisonAI TUI.
|
|
3
|
+
|
|
4
|
+
Defines event types for communication between TUI components.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from dataclasses import dataclass, field
|
|
8
|
+
from enum import Enum
|
|
9
|
+
from typing import Any, Dict, Optional
|
|
10
|
+
import time
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class TUIEventType(str, Enum):
|
|
14
|
+
"""Types of TUI events."""
|
|
15
|
+
# User input events
|
|
16
|
+
MESSAGE_SUBMITTED = "message_submitted"
|
|
17
|
+
COMMAND_EXECUTED = "command_executed"
|
|
18
|
+
|
|
19
|
+
# Queue events
|
|
20
|
+
RUN_QUEUED = "run_queued"
|
|
21
|
+
RUN_STARTED = "run_started"
|
|
22
|
+
RUN_COMPLETED = "run_completed"
|
|
23
|
+
RUN_FAILED = "run_failed"
|
|
24
|
+
RUN_CANCELLED = "run_cancelled"
|
|
25
|
+
|
|
26
|
+
# Output events
|
|
27
|
+
OUTPUT_CHUNK = "output_chunk"
|
|
28
|
+
OUTPUT_COMPLETE = "output_complete"
|
|
29
|
+
|
|
30
|
+
# Tool events
|
|
31
|
+
TOOL_CALL_STARTED = "tool_call_started"
|
|
32
|
+
TOOL_CALL_COMPLETED = "tool_call_completed"
|
|
33
|
+
TOOL_APPROVAL_REQUIRED = "tool_approval_required"
|
|
34
|
+
|
|
35
|
+
# Session events
|
|
36
|
+
SESSION_STARTED = "session_started"
|
|
37
|
+
SESSION_SAVED = "session_saved"
|
|
38
|
+
SESSION_LOADED = "session_loaded"
|
|
39
|
+
|
|
40
|
+
# UI events
|
|
41
|
+
SCREEN_CHANGED = "screen_changed"
|
|
42
|
+
FOCUS_CHANGED = "focus_changed"
|
|
43
|
+
ERROR_OCCURRED = "error_occurred"
|
|
44
|
+
STATUS_UPDATED = "status_updated"
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@dataclass
|
|
48
|
+
class TUIEvent:
|
|
49
|
+
"""A TUI event."""
|
|
50
|
+
event_type: TUIEventType
|
|
51
|
+
timestamp: float = field(default_factory=time.time)
|
|
52
|
+
data: Dict[str, Any] = field(default_factory=dict)
|
|
53
|
+
|
|
54
|
+
# Optional identifiers
|
|
55
|
+
run_id: Optional[str] = None
|
|
56
|
+
session_id: Optional[str] = None
|
|
57
|
+
agent_name: Optional[str] = None
|
|
58
|
+
|
|
59
|
+
@classmethod
|
|
60
|
+
def message_submitted(cls, content: str, **kwargs) -> "TUIEvent":
|
|
61
|
+
"""Create a message submitted event."""
|
|
62
|
+
return cls(
|
|
63
|
+
event_type=TUIEventType.MESSAGE_SUBMITTED,
|
|
64
|
+
data={"content": content, **kwargs}
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
@classmethod
|
|
68
|
+
def output_chunk(cls, run_id: str, content: str, **kwargs) -> "TUIEvent":
|
|
69
|
+
"""Create an output chunk event."""
|
|
70
|
+
return cls(
|
|
71
|
+
event_type=TUIEventType.OUTPUT_CHUNK,
|
|
72
|
+
run_id=run_id,
|
|
73
|
+
data={"content": content, **kwargs}
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
@classmethod
|
|
77
|
+
def run_completed(cls, run_id: str, output: str, **kwargs) -> "TUIEvent":
|
|
78
|
+
"""Create a run completed event."""
|
|
79
|
+
return cls(
|
|
80
|
+
event_type=TUIEventType.RUN_COMPLETED,
|
|
81
|
+
run_id=run_id,
|
|
82
|
+
data={"output": output, **kwargs}
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
@classmethod
|
|
86
|
+
def error(cls, message: str, **kwargs) -> "TUIEvent":
|
|
87
|
+
"""Create an error event."""
|
|
88
|
+
return cls(
|
|
89
|
+
event_type=TUIEventType.ERROR_OCCURRED,
|
|
90
|
+
data={"message": message, **kwargs}
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
@classmethod
|
|
94
|
+
def status_update(cls, status: str, **kwargs) -> "TUIEvent":
|
|
95
|
+
"""Create a status update event."""
|
|
96
|
+
return cls(
|
|
97
|
+
event_type=TUIEventType.STATUS_UPDATED,
|
|
98
|
+
data={"status": status, **kwargs}
|
|
99
|
+
)
|