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,810 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Debug CLI handler for PraisonAI.
|
|
3
|
+
|
|
4
|
+
Provides non-interactive debug commands for testing interactive flows:
|
|
5
|
+
- debug interactive: Run single interactive turn
|
|
6
|
+
- debug lsp: Direct LSP probes
|
|
7
|
+
- debug acp: Direct ACP probes
|
|
8
|
+
- debug trace: Trace record/replay/diff
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import argparse
|
|
12
|
+
import asyncio
|
|
13
|
+
import json
|
|
14
|
+
import logging
|
|
15
|
+
import sys
|
|
16
|
+
import time
|
|
17
|
+
from typing import Any, Dict, List
|
|
18
|
+
|
|
19
|
+
logger = logging.getLogger(__name__)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class DebugHandler:
|
|
23
|
+
"""Handler for debug CLI commands."""
|
|
24
|
+
|
|
25
|
+
@staticmethod
|
|
26
|
+
def setup_subparser(subparsers) -> None:
|
|
27
|
+
"""Set up the debug subcommand parser."""
|
|
28
|
+
debug_parser = subparsers.add_parser(
|
|
29
|
+
"debug",
|
|
30
|
+
help="Debug and test interactive flows",
|
|
31
|
+
description="Debug commands for testing interactive coding assistant flows"
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
debug_subparsers = debug_parser.add_subparsers(dest="debug_command", help="Debug subcommands")
|
|
35
|
+
|
|
36
|
+
# debug interactive
|
|
37
|
+
interactive_parser = debug_subparsers.add_parser(
|
|
38
|
+
"interactive",
|
|
39
|
+
help="Run single interactive turn non-interactively",
|
|
40
|
+
description="Execute one interactive turn with full LSP/ACP pipeline"
|
|
41
|
+
)
|
|
42
|
+
interactive_parser.add_argument(
|
|
43
|
+
"-p", "--prompt",
|
|
44
|
+
type=str,
|
|
45
|
+
required=True,
|
|
46
|
+
help="Prompt to execute"
|
|
47
|
+
)
|
|
48
|
+
interactive_parser.add_argument(
|
|
49
|
+
"--lsp",
|
|
50
|
+
action="store_true",
|
|
51
|
+
default=True,
|
|
52
|
+
help="Enable LSP (default: enabled)"
|
|
53
|
+
)
|
|
54
|
+
interactive_parser.add_argument(
|
|
55
|
+
"--no-lsp",
|
|
56
|
+
action="store_true",
|
|
57
|
+
help="Disable LSP"
|
|
58
|
+
)
|
|
59
|
+
interactive_parser.add_argument(
|
|
60
|
+
"--acp",
|
|
61
|
+
action="store_true",
|
|
62
|
+
default=True,
|
|
63
|
+
help="Enable ACP (default: enabled)"
|
|
64
|
+
)
|
|
65
|
+
interactive_parser.add_argument(
|
|
66
|
+
"--no-acp",
|
|
67
|
+
action="store_true",
|
|
68
|
+
help="Disable ACP"
|
|
69
|
+
)
|
|
70
|
+
interactive_parser.add_argument(
|
|
71
|
+
"--approval",
|
|
72
|
+
type=str,
|
|
73
|
+
choices=["manual", "auto", "scoped"],
|
|
74
|
+
default="auto",
|
|
75
|
+
help="Approval mode (default: auto for debug)"
|
|
76
|
+
)
|
|
77
|
+
interactive_parser.add_argument(
|
|
78
|
+
"--workspace", "-w",
|
|
79
|
+
type=str,
|
|
80
|
+
default=".",
|
|
81
|
+
help="Workspace root directory"
|
|
82
|
+
)
|
|
83
|
+
interactive_parser.add_argument(
|
|
84
|
+
"--json",
|
|
85
|
+
action="store_true",
|
|
86
|
+
help="Output JSON trace"
|
|
87
|
+
)
|
|
88
|
+
interactive_parser.add_argument(
|
|
89
|
+
"--trace-file",
|
|
90
|
+
type=str,
|
|
91
|
+
help="Save trace to file"
|
|
92
|
+
)
|
|
93
|
+
interactive_parser.add_argument(
|
|
94
|
+
"--timeout",
|
|
95
|
+
type=float,
|
|
96
|
+
default=60.0,
|
|
97
|
+
help="Timeout in seconds"
|
|
98
|
+
)
|
|
99
|
+
interactive_parser.add_argument(
|
|
100
|
+
"--model",
|
|
101
|
+
type=str,
|
|
102
|
+
help="LLM model to use"
|
|
103
|
+
)
|
|
104
|
+
interactive_parser.set_defaults(func=DebugHandler.handle_interactive)
|
|
105
|
+
|
|
106
|
+
# debug lsp
|
|
107
|
+
lsp_parser = debug_subparsers.add_parser(
|
|
108
|
+
"lsp",
|
|
109
|
+
help="Direct LSP probes",
|
|
110
|
+
description="Probe LSP server directly"
|
|
111
|
+
)
|
|
112
|
+
lsp_subparsers = lsp_parser.add_subparsers(dest="lsp_command", help="LSP subcommands")
|
|
113
|
+
|
|
114
|
+
# debug lsp status
|
|
115
|
+
lsp_status = lsp_subparsers.add_parser("status", help="Show LSP status")
|
|
116
|
+
lsp_status.add_argument("--workspace", "-w", type=str, default=".")
|
|
117
|
+
lsp_status.add_argument("--json", action="store_true")
|
|
118
|
+
lsp_status.set_defaults(func=DebugHandler.handle_lsp_status)
|
|
119
|
+
|
|
120
|
+
# debug lsp symbols
|
|
121
|
+
lsp_symbols = lsp_subparsers.add_parser("symbols", help="List symbols in file")
|
|
122
|
+
lsp_symbols.add_argument("file", type=str, help="File path")
|
|
123
|
+
lsp_symbols.add_argument("--workspace", "-w", type=str, default=".")
|
|
124
|
+
lsp_symbols.add_argument("--json", action="store_true")
|
|
125
|
+
lsp_symbols.set_defaults(func=DebugHandler.handle_lsp_symbols)
|
|
126
|
+
|
|
127
|
+
# debug lsp definition
|
|
128
|
+
lsp_def = lsp_subparsers.add_parser("definition", help="Get definition location")
|
|
129
|
+
lsp_def.add_argument("location", type=str, help="file:line:col")
|
|
130
|
+
lsp_def.add_argument("--workspace", "-w", type=str, default=".")
|
|
131
|
+
lsp_def.add_argument("--json", action="store_true")
|
|
132
|
+
lsp_def.set_defaults(func=DebugHandler.handle_lsp_definition)
|
|
133
|
+
|
|
134
|
+
# debug lsp references
|
|
135
|
+
lsp_refs = lsp_subparsers.add_parser("references", help="Get references")
|
|
136
|
+
lsp_refs.add_argument("location", type=str, help="file:line:col")
|
|
137
|
+
lsp_refs.add_argument("--workspace", "-w", type=str, default=".")
|
|
138
|
+
lsp_refs.add_argument("--json", action="store_true")
|
|
139
|
+
lsp_refs.set_defaults(func=DebugHandler.handle_lsp_references)
|
|
140
|
+
|
|
141
|
+
# debug lsp diagnostics
|
|
142
|
+
lsp_diag = lsp_subparsers.add_parser("diagnostics", help="Get diagnostics")
|
|
143
|
+
lsp_diag.add_argument("file", type=str, nargs="?", help="File path (optional)")
|
|
144
|
+
lsp_diag.add_argument("--all", action="store_true", help="Get all diagnostics")
|
|
145
|
+
lsp_diag.add_argument("--workspace", "-w", type=str, default=".")
|
|
146
|
+
lsp_diag.add_argument("--json", action="store_true")
|
|
147
|
+
lsp_diag.set_defaults(func=DebugHandler.handle_lsp_diagnostics)
|
|
148
|
+
|
|
149
|
+
# debug acp
|
|
150
|
+
acp_parser = debug_subparsers.add_parser(
|
|
151
|
+
"acp",
|
|
152
|
+
help="Direct ACP probes",
|
|
153
|
+
description="Probe ACP server directly"
|
|
154
|
+
)
|
|
155
|
+
acp_subparsers = acp_parser.add_subparsers(dest="acp_command", help="ACP subcommands")
|
|
156
|
+
|
|
157
|
+
# debug acp status
|
|
158
|
+
acp_status = acp_subparsers.add_parser("status", help="Show ACP status")
|
|
159
|
+
acp_status.add_argument("--workspace", "-w", type=str, default=".")
|
|
160
|
+
acp_status.add_argument("--json", action="store_true")
|
|
161
|
+
acp_status.set_defaults(func=DebugHandler.handle_acp_status)
|
|
162
|
+
|
|
163
|
+
# debug acp plan
|
|
164
|
+
acp_plan = acp_subparsers.add_parser("plan", help="Create action plan")
|
|
165
|
+
acp_plan.add_argument("-p", "--prompt", type=str, required=True)
|
|
166
|
+
acp_plan.add_argument("--workspace", "-w", type=str, default=".")
|
|
167
|
+
acp_plan.add_argument("--json", action="store_true")
|
|
168
|
+
acp_plan.set_defaults(func=DebugHandler.handle_acp_plan)
|
|
169
|
+
|
|
170
|
+
# debug acp apply
|
|
171
|
+
acp_apply = acp_subparsers.add_parser("apply", help="Apply action plan")
|
|
172
|
+
acp_apply.add_argument("-p", "--prompt", type=str, required=True)
|
|
173
|
+
acp_apply.add_argument("--approval", type=str, choices=["manual", "auto", "scoped"], default="auto")
|
|
174
|
+
acp_apply.add_argument("--workspace", "-w", type=str, default=".")
|
|
175
|
+
acp_apply.add_argument("--json", action="store_true")
|
|
176
|
+
acp_apply.set_defaults(func=DebugHandler.handle_acp_apply)
|
|
177
|
+
|
|
178
|
+
# debug trace
|
|
179
|
+
trace_parser = debug_subparsers.add_parser(
|
|
180
|
+
"trace",
|
|
181
|
+
help="Trace record/replay/diff",
|
|
182
|
+
description="Manage trace recordings"
|
|
183
|
+
)
|
|
184
|
+
trace_subparsers = trace_parser.add_subparsers(dest="trace_command", help="Trace subcommands")
|
|
185
|
+
|
|
186
|
+
# debug trace record
|
|
187
|
+
trace_record = trace_subparsers.add_parser("record", help="Record session trace")
|
|
188
|
+
trace_record.add_argument("-o", "--output", type=str, required=True, help="Output file")
|
|
189
|
+
trace_record.set_defaults(func=DebugHandler.handle_trace_record)
|
|
190
|
+
|
|
191
|
+
# debug trace replay
|
|
192
|
+
trace_replay = trace_subparsers.add_parser("replay", help="Replay recorded trace")
|
|
193
|
+
trace_replay.add_argument("file", type=str, help="Trace file to replay")
|
|
194
|
+
trace_replay.add_argument("--json", action="store_true")
|
|
195
|
+
trace_replay.set_defaults(func=DebugHandler.handle_trace_replay)
|
|
196
|
+
|
|
197
|
+
# debug trace diff
|
|
198
|
+
trace_diff = trace_subparsers.add_parser("diff", help="Compare two traces")
|
|
199
|
+
trace_diff.add_argument("file1", type=str, help="First trace file")
|
|
200
|
+
trace_diff.add_argument("file2", type=str, help="Second trace file")
|
|
201
|
+
trace_diff.add_argument("--json", action="store_true")
|
|
202
|
+
trace_diff.set_defaults(func=DebugHandler.handle_trace_diff)
|
|
203
|
+
|
|
204
|
+
@staticmethod
|
|
205
|
+
def handle_interactive(args: argparse.Namespace) -> int:
|
|
206
|
+
"""Handle debug interactive command."""
|
|
207
|
+
return asyncio.run(DebugHandler._run_interactive(args))
|
|
208
|
+
|
|
209
|
+
@staticmethod
|
|
210
|
+
async def _run_interactive(args: argparse.Namespace) -> int:
|
|
211
|
+
"""Run interactive turn asynchronously."""
|
|
212
|
+
from .interactive_runtime import create_runtime
|
|
213
|
+
from .code_intelligence import CodeIntelligenceRouter
|
|
214
|
+
from .action_orchestrator import ActionOrchestrator
|
|
215
|
+
|
|
216
|
+
start_time = time.time()
|
|
217
|
+
|
|
218
|
+
# Create runtime
|
|
219
|
+
runtime = create_runtime(
|
|
220
|
+
workspace=args.workspace,
|
|
221
|
+
lsp=args.lsp and not args.no_lsp,
|
|
222
|
+
acp=args.acp and not args.no_acp,
|
|
223
|
+
approval=args.approval,
|
|
224
|
+
trace=True,
|
|
225
|
+
trace_file=args.trace_file,
|
|
226
|
+
json_output=args.json,
|
|
227
|
+
timeout=args.timeout,
|
|
228
|
+
model=getattr(args, 'model', None)
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
result = {
|
|
232
|
+
"prompt": args.prompt,
|
|
233
|
+
"workspace": args.workspace,
|
|
234
|
+
"start_time": start_time
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
try:
|
|
238
|
+
# Start runtime
|
|
239
|
+
status = await runtime.start()
|
|
240
|
+
result["runtime_status"] = status
|
|
241
|
+
|
|
242
|
+
if not status.get("started"):
|
|
243
|
+
result["error"] = "Failed to start runtime"
|
|
244
|
+
DebugHandler._output_result(result, args.json)
|
|
245
|
+
return 1
|
|
246
|
+
|
|
247
|
+
# Classify intent
|
|
248
|
+
code_router = CodeIntelligenceRouter(runtime)
|
|
249
|
+
action_orchestrator = ActionOrchestrator(runtime)
|
|
250
|
+
|
|
251
|
+
prompt = args.prompt.lower()
|
|
252
|
+
|
|
253
|
+
# Determine if this is a code query or action
|
|
254
|
+
is_code_query = any(kw in prompt for kw in [
|
|
255
|
+
"list", "show", "find", "where", "definition", "reference",
|
|
256
|
+
"symbol", "function", "class", "diagnostic", "error"
|
|
257
|
+
])
|
|
258
|
+
|
|
259
|
+
is_action = any(kw in prompt for kw in [
|
|
260
|
+
"create", "edit", "modify", "delete", "rename", "add", "remove",
|
|
261
|
+
"change", "update", "refactor"
|
|
262
|
+
])
|
|
263
|
+
|
|
264
|
+
if is_code_query:
|
|
265
|
+
# Route to code intelligence
|
|
266
|
+
query_result = await code_router.handle_query(args.prompt)
|
|
267
|
+
result["type"] = "code_query"
|
|
268
|
+
result["query_result"] = query_result.to_dict()
|
|
269
|
+
result["lsp_used"] = query_result.lsp_used
|
|
270
|
+
result["citations"] = query_result.citations
|
|
271
|
+
|
|
272
|
+
elif is_action:
|
|
273
|
+
# Route to action orchestrator
|
|
274
|
+
action_result = await action_orchestrator.execute(
|
|
275
|
+
args.prompt,
|
|
276
|
+
auto_approve=(args.approval == "auto")
|
|
277
|
+
)
|
|
278
|
+
result["type"] = "action"
|
|
279
|
+
result["action_result"] = action_result.to_dict()
|
|
280
|
+
result["read_only_blocked"] = action_result.read_only_blocked
|
|
281
|
+
|
|
282
|
+
else:
|
|
283
|
+
# General query - just return status
|
|
284
|
+
result["type"] = "general"
|
|
285
|
+
result["message"] = "Query processed"
|
|
286
|
+
|
|
287
|
+
# Get trace
|
|
288
|
+
trace = runtime.get_trace()
|
|
289
|
+
if trace:
|
|
290
|
+
result["trace"] = trace.to_dict()
|
|
291
|
+
|
|
292
|
+
result["success"] = True
|
|
293
|
+
|
|
294
|
+
except Exception as e:
|
|
295
|
+
result["error"] = str(e)
|
|
296
|
+
result["success"] = False
|
|
297
|
+
logger.exception("Debug interactive failed")
|
|
298
|
+
|
|
299
|
+
finally:
|
|
300
|
+
await runtime.stop()
|
|
301
|
+
result["end_time"] = time.time()
|
|
302
|
+
result["duration_ms"] = (result["end_time"] - start_time) * 1000
|
|
303
|
+
|
|
304
|
+
# Save trace if requested
|
|
305
|
+
if args.trace_file and "trace" in result:
|
|
306
|
+
with open(args.trace_file, "w") as f:
|
|
307
|
+
json.dump(result["trace"], f, indent=2, default=str)
|
|
308
|
+
if not args.json:
|
|
309
|
+
print(f"Trace saved to: {args.trace_file}")
|
|
310
|
+
|
|
311
|
+
DebugHandler._output_result(result, args.json)
|
|
312
|
+
return 0 if result.get("success") else 1
|
|
313
|
+
|
|
314
|
+
@staticmethod
|
|
315
|
+
def handle_lsp_status(args: argparse.Namespace) -> int:
|
|
316
|
+
"""Handle debug lsp status command."""
|
|
317
|
+
return asyncio.run(DebugHandler._run_lsp_status(args))
|
|
318
|
+
|
|
319
|
+
@staticmethod
|
|
320
|
+
async def _run_lsp_status(args: argparse.Namespace) -> int:
|
|
321
|
+
"""Run LSP status check."""
|
|
322
|
+
from .interactive_runtime import create_runtime
|
|
323
|
+
|
|
324
|
+
runtime = create_runtime(
|
|
325
|
+
workspace=args.workspace,
|
|
326
|
+
lsp=True,
|
|
327
|
+
acp=False
|
|
328
|
+
)
|
|
329
|
+
|
|
330
|
+
try:
|
|
331
|
+
await runtime.start()
|
|
332
|
+
result = {
|
|
333
|
+
"lsp_enabled": True,
|
|
334
|
+
"lsp_ready": runtime.lsp_ready,
|
|
335
|
+
"lsp_status": runtime._lsp_state.status.value,
|
|
336
|
+
"lsp_error": runtime._lsp_state.error,
|
|
337
|
+
"workspace": args.workspace
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
DebugHandler._output_result(result, args.json)
|
|
341
|
+
return 0 if runtime.lsp_ready else 1
|
|
342
|
+
|
|
343
|
+
finally:
|
|
344
|
+
await runtime.stop()
|
|
345
|
+
|
|
346
|
+
@staticmethod
|
|
347
|
+
def handle_lsp_symbols(args: argparse.Namespace) -> int:
|
|
348
|
+
"""Handle debug lsp symbols command."""
|
|
349
|
+
return asyncio.run(DebugHandler._run_lsp_symbols(args))
|
|
350
|
+
|
|
351
|
+
@staticmethod
|
|
352
|
+
async def _run_lsp_symbols(args: argparse.Namespace) -> int:
|
|
353
|
+
"""Run LSP symbols query."""
|
|
354
|
+
from .interactive_runtime import create_runtime
|
|
355
|
+
from .code_intelligence import CodeIntelligenceRouter
|
|
356
|
+
|
|
357
|
+
runtime = create_runtime(
|
|
358
|
+
workspace=args.workspace,
|
|
359
|
+
lsp=True,
|
|
360
|
+
acp=False
|
|
361
|
+
)
|
|
362
|
+
|
|
363
|
+
try:
|
|
364
|
+
await runtime.start()
|
|
365
|
+
|
|
366
|
+
if not runtime.lsp_ready:
|
|
367
|
+
# Use fallback
|
|
368
|
+
router = CodeIntelligenceRouter(runtime)
|
|
369
|
+
result = await router._fallback_list_symbols(args.file)
|
|
370
|
+
else:
|
|
371
|
+
symbols = await runtime.lsp_get_symbols(args.file)
|
|
372
|
+
result = {
|
|
373
|
+
"file": args.file,
|
|
374
|
+
"symbols": symbols,
|
|
375
|
+
"count": len(symbols) if symbols else 0,
|
|
376
|
+
"lsp_used": True
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
if hasattr(result, 'to_dict'):
|
|
380
|
+
result = result.to_dict()
|
|
381
|
+
|
|
382
|
+
DebugHandler._output_result(result, args.json)
|
|
383
|
+
return 0
|
|
384
|
+
|
|
385
|
+
finally:
|
|
386
|
+
await runtime.stop()
|
|
387
|
+
|
|
388
|
+
@staticmethod
|
|
389
|
+
def handle_lsp_definition(args: argparse.Namespace) -> int:
|
|
390
|
+
"""Handle debug lsp definition command."""
|
|
391
|
+
return asyncio.run(DebugHandler._run_lsp_definition(args))
|
|
392
|
+
|
|
393
|
+
@staticmethod
|
|
394
|
+
async def _run_lsp_definition(args: argparse.Namespace) -> int:
|
|
395
|
+
"""Run LSP definition query."""
|
|
396
|
+
from .interactive_runtime import create_runtime
|
|
397
|
+
|
|
398
|
+
# Parse location
|
|
399
|
+
parts = args.location.split(":")
|
|
400
|
+
if len(parts) != 3:
|
|
401
|
+
print("Error: Location must be in format file:line:col", file=sys.stderr)
|
|
402
|
+
return 1
|
|
403
|
+
|
|
404
|
+
file_path, line, col = parts[0], int(parts[1]), int(parts[2])
|
|
405
|
+
|
|
406
|
+
runtime = create_runtime(
|
|
407
|
+
workspace=args.workspace,
|
|
408
|
+
lsp=True,
|
|
409
|
+
acp=False
|
|
410
|
+
)
|
|
411
|
+
|
|
412
|
+
try:
|
|
413
|
+
await runtime.start()
|
|
414
|
+
|
|
415
|
+
definitions = await runtime.lsp_get_definition(file_path, line, col)
|
|
416
|
+
result = {
|
|
417
|
+
"file": file_path,
|
|
418
|
+
"line": line,
|
|
419
|
+
"col": col,
|
|
420
|
+
"definitions": definitions,
|
|
421
|
+
"count": len(definitions) if definitions else 0,
|
|
422
|
+
"lsp_used": runtime.lsp_ready
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
DebugHandler._output_result(result, args.json)
|
|
426
|
+
return 0
|
|
427
|
+
|
|
428
|
+
finally:
|
|
429
|
+
await runtime.stop()
|
|
430
|
+
|
|
431
|
+
@staticmethod
|
|
432
|
+
def handle_lsp_references(args: argparse.Namespace) -> int:
|
|
433
|
+
"""Handle debug lsp references command."""
|
|
434
|
+
return asyncio.run(DebugHandler._run_lsp_references(args))
|
|
435
|
+
|
|
436
|
+
@staticmethod
|
|
437
|
+
async def _run_lsp_references(args: argparse.Namespace) -> int:
|
|
438
|
+
"""Run LSP references query."""
|
|
439
|
+
from .interactive_runtime import create_runtime
|
|
440
|
+
|
|
441
|
+
# Parse location
|
|
442
|
+
parts = args.location.split(":")
|
|
443
|
+
if len(parts) != 3:
|
|
444
|
+
print("Error: Location must be in format file:line:col", file=sys.stderr)
|
|
445
|
+
return 1
|
|
446
|
+
|
|
447
|
+
file_path, line, col = parts[0], int(parts[1]), int(parts[2])
|
|
448
|
+
|
|
449
|
+
runtime = create_runtime(
|
|
450
|
+
workspace=args.workspace,
|
|
451
|
+
lsp=True,
|
|
452
|
+
acp=False
|
|
453
|
+
)
|
|
454
|
+
|
|
455
|
+
try:
|
|
456
|
+
await runtime.start()
|
|
457
|
+
|
|
458
|
+
references = await runtime.lsp_get_references(file_path, line, col)
|
|
459
|
+
result = {
|
|
460
|
+
"file": file_path,
|
|
461
|
+
"line": line,
|
|
462
|
+
"col": col,
|
|
463
|
+
"references": references,
|
|
464
|
+
"count": len(references) if references else 0,
|
|
465
|
+
"lsp_used": runtime.lsp_ready
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
DebugHandler._output_result(result, args.json)
|
|
469
|
+
return 0
|
|
470
|
+
|
|
471
|
+
finally:
|
|
472
|
+
await runtime.stop()
|
|
473
|
+
|
|
474
|
+
@staticmethod
|
|
475
|
+
def handle_lsp_diagnostics(args: argparse.Namespace) -> int:
|
|
476
|
+
"""Handle debug lsp diagnostics command."""
|
|
477
|
+
return asyncio.run(DebugHandler._run_lsp_diagnostics(args))
|
|
478
|
+
|
|
479
|
+
@staticmethod
|
|
480
|
+
async def _run_lsp_diagnostics(args: argparse.Namespace) -> int:
|
|
481
|
+
"""Run LSP diagnostics query."""
|
|
482
|
+
from .interactive_runtime import create_runtime
|
|
483
|
+
|
|
484
|
+
runtime = create_runtime(
|
|
485
|
+
workspace=args.workspace,
|
|
486
|
+
lsp=True,
|
|
487
|
+
acp=False
|
|
488
|
+
)
|
|
489
|
+
|
|
490
|
+
try:
|
|
491
|
+
await runtime.start()
|
|
492
|
+
|
|
493
|
+
file_path = args.file if not args.all else None
|
|
494
|
+
diagnostics = await runtime.lsp_get_diagnostics(file_path)
|
|
495
|
+
|
|
496
|
+
result = {
|
|
497
|
+
"file": file_path or "all",
|
|
498
|
+
"diagnostics": diagnostics,
|
|
499
|
+
"count": len(diagnostics) if diagnostics else 0,
|
|
500
|
+
"lsp_used": runtime.lsp_ready
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
DebugHandler._output_result(result, args.json)
|
|
504
|
+
return 0
|
|
505
|
+
|
|
506
|
+
finally:
|
|
507
|
+
await runtime.stop()
|
|
508
|
+
|
|
509
|
+
@staticmethod
|
|
510
|
+
def handle_acp_status(args: argparse.Namespace) -> int:
|
|
511
|
+
"""Handle debug acp status command."""
|
|
512
|
+
return asyncio.run(DebugHandler._run_acp_status(args))
|
|
513
|
+
|
|
514
|
+
@staticmethod
|
|
515
|
+
async def _run_acp_status(args: argparse.Namespace) -> int:
|
|
516
|
+
"""Run ACP status check."""
|
|
517
|
+
from .interactive_runtime import create_runtime
|
|
518
|
+
|
|
519
|
+
runtime = create_runtime(
|
|
520
|
+
workspace=args.workspace,
|
|
521
|
+
lsp=False,
|
|
522
|
+
acp=True
|
|
523
|
+
)
|
|
524
|
+
|
|
525
|
+
try:
|
|
526
|
+
await runtime.start()
|
|
527
|
+
result = {
|
|
528
|
+
"acp_enabled": True,
|
|
529
|
+
"acp_ready": runtime.acp_ready,
|
|
530
|
+
"acp_status": runtime._acp_state.status.value,
|
|
531
|
+
"acp_error": runtime._acp_state.error,
|
|
532
|
+
"read_only": runtime.read_only,
|
|
533
|
+
"workspace": args.workspace
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
DebugHandler._output_result(result, args.json)
|
|
537
|
+
return 0 if runtime.acp_ready else 1
|
|
538
|
+
|
|
539
|
+
finally:
|
|
540
|
+
await runtime.stop()
|
|
541
|
+
|
|
542
|
+
@staticmethod
|
|
543
|
+
def handle_acp_plan(args: argparse.Namespace) -> int:
|
|
544
|
+
"""Handle debug acp plan command."""
|
|
545
|
+
return asyncio.run(DebugHandler._run_acp_plan(args))
|
|
546
|
+
|
|
547
|
+
@staticmethod
|
|
548
|
+
async def _run_acp_plan(args: argparse.Namespace) -> int:
|
|
549
|
+
"""Run ACP plan creation."""
|
|
550
|
+
from .interactive_runtime import create_runtime
|
|
551
|
+
from .action_orchestrator import ActionOrchestrator
|
|
552
|
+
|
|
553
|
+
runtime = create_runtime(
|
|
554
|
+
workspace=args.workspace,
|
|
555
|
+
lsp=False,
|
|
556
|
+
acp=True
|
|
557
|
+
)
|
|
558
|
+
|
|
559
|
+
try:
|
|
560
|
+
await runtime.start()
|
|
561
|
+
|
|
562
|
+
orchestrator = ActionOrchestrator(runtime)
|
|
563
|
+
result = await orchestrator.create_plan(args.prompt)
|
|
564
|
+
|
|
565
|
+
DebugHandler._output_result(result.to_dict(), args.json)
|
|
566
|
+
return 0 if result.success else 1
|
|
567
|
+
|
|
568
|
+
finally:
|
|
569
|
+
await runtime.stop()
|
|
570
|
+
|
|
571
|
+
@staticmethod
|
|
572
|
+
def handle_acp_apply(args: argparse.Namespace) -> int:
|
|
573
|
+
"""Handle debug acp apply command."""
|
|
574
|
+
return asyncio.run(DebugHandler._run_acp_apply(args))
|
|
575
|
+
|
|
576
|
+
@staticmethod
|
|
577
|
+
async def _run_acp_apply(args: argparse.Namespace) -> int:
|
|
578
|
+
"""Run ACP plan and apply."""
|
|
579
|
+
from .interactive_runtime import create_runtime
|
|
580
|
+
from .action_orchestrator import ActionOrchestrator
|
|
581
|
+
|
|
582
|
+
runtime = create_runtime(
|
|
583
|
+
workspace=args.workspace,
|
|
584
|
+
lsp=False,
|
|
585
|
+
acp=True,
|
|
586
|
+
approval=args.approval
|
|
587
|
+
)
|
|
588
|
+
|
|
589
|
+
try:
|
|
590
|
+
await runtime.start()
|
|
591
|
+
|
|
592
|
+
orchestrator = ActionOrchestrator(runtime)
|
|
593
|
+
result = await orchestrator.execute(
|
|
594
|
+
args.prompt,
|
|
595
|
+
auto_approve=(args.approval == "auto")
|
|
596
|
+
)
|
|
597
|
+
|
|
598
|
+
DebugHandler._output_result(result.to_dict(), args.json)
|
|
599
|
+
return 0 if result.success else 1
|
|
600
|
+
|
|
601
|
+
finally:
|
|
602
|
+
await runtime.stop()
|
|
603
|
+
|
|
604
|
+
@staticmethod
|
|
605
|
+
def handle_trace_record(args: argparse.Namespace) -> int:
|
|
606
|
+
"""Handle debug trace record command."""
|
|
607
|
+
print(f"Trace recording will be saved to: {args.output}")
|
|
608
|
+
print("Start an interactive session with --trace-file to record.")
|
|
609
|
+
return 0
|
|
610
|
+
|
|
611
|
+
@staticmethod
|
|
612
|
+
def handle_trace_replay(args: argparse.Namespace) -> int:
|
|
613
|
+
"""Handle debug trace replay command."""
|
|
614
|
+
try:
|
|
615
|
+
with open(args.file) as f:
|
|
616
|
+
trace = json.load(f)
|
|
617
|
+
|
|
618
|
+
if args.json:
|
|
619
|
+
print(json.dumps(trace, indent=2))
|
|
620
|
+
else:
|
|
621
|
+
print(f"Trace from: {args.file}")
|
|
622
|
+
print(f"Start time: {trace.get('start_time')}")
|
|
623
|
+
print(f"End time: {trace.get('end_time')}")
|
|
624
|
+
print(f"Entries: {len(trace.get('entries', []))}")
|
|
625
|
+
print("\nEntries:")
|
|
626
|
+
for entry in trace.get("entries", []):
|
|
627
|
+
print(f" [{entry.get('category')}] {entry.get('action')}")
|
|
628
|
+
if entry.get('duration_ms'):
|
|
629
|
+
print(f" Duration: {entry.get('duration_ms'):.2f}ms")
|
|
630
|
+
if entry.get('error'):
|
|
631
|
+
print(f" Error: {entry.get('error')}")
|
|
632
|
+
|
|
633
|
+
return 0
|
|
634
|
+
except Exception as e:
|
|
635
|
+
print(f"Error: {e}", file=sys.stderr)
|
|
636
|
+
return 1
|
|
637
|
+
|
|
638
|
+
@staticmethod
|
|
639
|
+
def handle_trace_diff(args: argparse.Namespace) -> int:
|
|
640
|
+
"""Handle debug trace diff command."""
|
|
641
|
+
try:
|
|
642
|
+
with open(args.file1) as f:
|
|
643
|
+
trace1 = json.load(f)
|
|
644
|
+
with open(args.file2) as f:
|
|
645
|
+
trace2 = json.load(f)
|
|
646
|
+
|
|
647
|
+
diff = {
|
|
648
|
+
"file1": args.file1,
|
|
649
|
+
"file2": args.file2,
|
|
650
|
+
"entries_diff": {
|
|
651
|
+
"file1_count": len(trace1.get("entries", [])),
|
|
652
|
+
"file2_count": len(trace2.get("entries", []))
|
|
653
|
+
},
|
|
654
|
+
"duration_diff": {
|
|
655
|
+
"file1": trace1.get("end_time", 0) - trace1.get("start_time", 0),
|
|
656
|
+
"file2": trace2.get("end_time", 0) - trace2.get("start_time", 0)
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
DebugHandler._output_result(diff, args.json)
|
|
661
|
+
return 0
|
|
662
|
+
except Exception as e:
|
|
663
|
+
print(f"Error: {e}", file=sys.stderr)
|
|
664
|
+
return 1
|
|
665
|
+
|
|
666
|
+
@staticmethod
|
|
667
|
+
def _output_result(result: Dict[str, Any], as_json: bool) -> None:
|
|
668
|
+
"""Output result in appropriate format."""
|
|
669
|
+
if as_json:
|
|
670
|
+
print(json.dumps(result, indent=2, default=str))
|
|
671
|
+
else:
|
|
672
|
+
for key, value in result.items():
|
|
673
|
+
if isinstance(value, dict):
|
|
674
|
+
print(f"{key}:")
|
|
675
|
+
for k, v in value.items():
|
|
676
|
+
print(f" {k}: {v}")
|
|
677
|
+
elif isinstance(value, list):
|
|
678
|
+
print(f"{key}: ({len(value)} items)")
|
|
679
|
+
for item in value[:5]: # Show first 5
|
|
680
|
+
print(f" - {item}")
|
|
681
|
+
if len(value) > 5:
|
|
682
|
+
print(f" ... and {len(value) - 5} more")
|
|
683
|
+
else:
|
|
684
|
+
print(f"{key}: {value}")
|
|
685
|
+
|
|
686
|
+
|
|
687
|
+
def setup_debug_subparser(subparsers) -> None:
|
|
688
|
+
"""Set up the debug subcommand parser."""
|
|
689
|
+
DebugHandler.setup_subparser(subparsers)
|
|
690
|
+
|
|
691
|
+
|
|
692
|
+
def run_debug_command(args: List[str]) -> int:
|
|
693
|
+
"""Run debug command from CLI."""
|
|
694
|
+
parser = argparse.ArgumentParser(
|
|
695
|
+
prog="praisonai debug",
|
|
696
|
+
description="Debug and test interactive coding assistant flows"
|
|
697
|
+
)
|
|
698
|
+
subparsers = parser.add_subparsers(dest="debug_command", help="Debug subcommands")
|
|
699
|
+
|
|
700
|
+
# debug interactive
|
|
701
|
+
interactive_parser = subparsers.add_parser(
|
|
702
|
+
"interactive",
|
|
703
|
+
help="Run single interactive turn non-interactively",
|
|
704
|
+
description="Execute one interactive turn with full LSP/ACP pipeline"
|
|
705
|
+
)
|
|
706
|
+
interactive_parser.add_argument("-p", "--prompt", type=str, required=True, help="Prompt to execute")
|
|
707
|
+
interactive_parser.add_argument("--lsp", action="store_true", default=True, help="Enable LSP (default: enabled)")
|
|
708
|
+
interactive_parser.add_argument("--no-lsp", action="store_true", help="Disable LSP")
|
|
709
|
+
interactive_parser.add_argument("--acp", action="store_true", default=True, help="Enable ACP (default: enabled)")
|
|
710
|
+
interactive_parser.add_argument("--no-acp", action="store_true", help="Disable ACP")
|
|
711
|
+
interactive_parser.add_argument("--approval", type=str, choices=["manual", "auto", "scoped"], default="auto", help="Approval mode")
|
|
712
|
+
interactive_parser.add_argument("--workspace", "-w", type=str, default=".", help="Workspace root directory")
|
|
713
|
+
interactive_parser.add_argument("--json", action="store_true", help="Output JSON trace")
|
|
714
|
+
interactive_parser.add_argument("--trace-file", type=str, help="Save trace to file")
|
|
715
|
+
interactive_parser.add_argument("--timeout", type=float, default=60.0, help="Timeout in seconds")
|
|
716
|
+
interactive_parser.add_argument("--model", type=str, help="LLM model to use")
|
|
717
|
+
interactive_parser.set_defaults(func=DebugHandler.handle_interactive)
|
|
718
|
+
|
|
719
|
+
# debug lsp
|
|
720
|
+
lsp_parser = subparsers.add_parser("lsp", help="Direct LSP probes")
|
|
721
|
+
lsp_subparsers = lsp_parser.add_subparsers(dest="lsp_command", help="LSP subcommands")
|
|
722
|
+
|
|
723
|
+
# debug lsp status
|
|
724
|
+
lsp_status = lsp_subparsers.add_parser("status", help="Show LSP status")
|
|
725
|
+
lsp_status.add_argument("--workspace", "-w", type=str, default=".")
|
|
726
|
+
lsp_status.add_argument("--json", action="store_true")
|
|
727
|
+
lsp_status.set_defaults(func=DebugHandler.handle_lsp_status)
|
|
728
|
+
|
|
729
|
+
# debug lsp symbols
|
|
730
|
+
lsp_symbols = lsp_subparsers.add_parser("symbols", help="List symbols in file")
|
|
731
|
+
lsp_symbols.add_argument("file", type=str, help="File path")
|
|
732
|
+
lsp_symbols.add_argument("--workspace", "-w", type=str, default=".")
|
|
733
|
+
lsp_symbols.add_argument("--json", action="store_true")
|
|
734
|
+
lsp_symbols.set_defaults(func=DebugHandler.handle_lsp_symbols)
|
|
735
|
+
|
|
736
|
+
# debug lsp definition
|
|
737
|
+
lsp_def = lsp_subparsers.add_parser("definition", help="Get definition location")
|
|
738
|
+
lsp_def.add_argument("location", type=str, help="file:line:col")
|
|
739
|
+
lsp_def.add_argument("--workspace", "-w", type=str, default=".")
|
|
740
|
+
lsp_def.add_argument("--json", action="store_true")
|
|
741
|
+
lsp_def.set_defaults(func=DebugHandler.handle_lsp_definition)
|
|
742
|
+
|
|
743
|
+
# debug lsp references
|
|
744
|
+
lsp_refs = lsp_subparsers.add_parser("references", help="Get references")
|
|
745
|
+
lsp_refs.add_argument("location", type=str, help="file:line:col")
|
|
746
|
+
lsp_refs.add_argument("--workspace", "-w", type=str, default=".")
|
|
747
|
+
lsp_refs.add_argument("--json", action="store_true")
|
|
748
|
+
lsp_refs.set_defaults(func=DebugHandler.handle_lsp_references)
|
|
749
|
+
|
|
750
|
+
# debug lsp diagnostics
|
|
751
|
+
lsp_diag = lsp_subparsers.add_parser("diagnostics", help="Get diagnostics")
|
|
752
|
+
lsp_diag.add_argument("file", type=str, nargs="?", help="File path (optional)")
|
|
753
|
+
lsp_diag.add_argument("--all", action="store_true", help="Get all diagnostics")
|
|
754
|
+
lsp_diag.add_argument("--workspace", "-w", type=str, default=".")
|
|
755
|
+
lsp_diag.add_argument("--json", action="store_true")
|
|
756
|
+
lsp_diag.set_defaults(func=DebugHandler.handle_lsp_diagnostics)
|
|
757
|
+
|
|
758
|
+
# debug acp
|
|
759
|
+
acp_parser = subparsers.add_parser("acp", help="Direct ACP probes")
|
|
760
|
+
acp_subparsers = acp_parser.add_subparsers(dest="acp_command", help="ACP subcommands")
|
|
761
|
+
|
|
762
|
+
# debug acp status
|
|
763
|
+
acp_status = acp_subparsers.add_parser("status", help="Show ACP status")
|
|
764
|
+
acp_status.add_argument("--workspace", "-w", type=str, default=".")
|
|
765
|
+
acp_status.add_argument("--json", action="store_true")
|
|
766
|
+
acp_status.set_defaults(func=DebugHandler.handle_acp_status)
|
|
767
|
+
|
|
768
|
+
# debug acp plan
|
|
769
|
+
acp_plan = acp_subparsers.add_parser("plan", help="Create action plan")
|
|
770
|
+
acp_plan.add_argument("-p", "--prompt", type=str, required=True)
|
|
771
|
+
acp_plan.add_argument("--workspace", "-w", type=str, default=".")
|
|
772
|
+
acp_plan.add_argument("--json", action="store_true")
|
|
773
|
+
acp_plan.set_defaults(func=DebugHandler.handle_acp_plan)
|
|
774
|
+
|
|
775
|
+
# debug acp apply
|
|
776
|
+
acp_apply = acp_subparsers.add_parser("apply", help="Apply action plan")
|
|
777
|
+
acp_apply.add_argument("-p", "--prompt", type=str, required=True)
|
|
778
|
+
acp_apply.add_argument("--approval", type=str, choices=["manual", "auto", "scoped"], default="auto")
|
|
779
|
+
acp_apply.add_argument("--workspace", "-w", type=str, default=".")
|
|
780
|
+
acp_apply.add_argument("--json", action="store_true")
|
|
781
|
+
acp_apply.set_defaults(func=DebugHandler.handle_acp_apply)
|
|
782
|
+
|
|
783
|
+
# debug trace
|
|
784
|
+
trace_parser = subparsers.add_parser("trace", help="Trace record/replay/diff")
|
|
785
|
+
trace_subparsers = trace_parser.add_subparsers(dest="trace_command", help="Trace subcommands")
|
|
786
|
+
|
|
787
|
+
# debug trace record
|
|
788
|
+
trace_record = trace_subparsers.add_parser("record", help="Record session trace")
|
|
789
|
+
trace_record.add_argument("-o", "--output", type=str, required=True, help="Output file")
|
|
790
|
+
trace_record.set_defaults(func=DebugHandler.handle_trace_record)
|
|
791
|
+
|
|
792
|
+
# debug trace replay
|
|
793
|
+
trace_replay = trace_subparsers.add_parser("replay", help="Replay recorded trace")
|
|
794
|
+
trace_replay.add_argument("file", type=str, help="Trace file to replay")
|
|
795
|
+
trace_replay.add_argument("--json", action="store_true")
|
|
796
|
+
trace_replay.set_defaults(func=DebugHandler.handle_trace_replay)
|
|
797
|
+
|
|
798
|
+
# debug trace diff
|
|
799
|
+
trace_diff = trace_subparsers.add_parser("diff", help="Compare two traces")
|
|
800
|
+
trace_diff.add_argument("file1", type=str, help="First trace file")
|
|
801
|
+
trace_diff.add_argument("file2", type=str, help="Second trace file")
|
|
802
|
+
trace_diff.add_argument("--json", action="store_true")
|
|
803
|
+
trace_diff.set_defaults(func=DebugHandler.handle_trace_diff)
|
|
804
|
+
|
|
805
|
+
parsed = parser.parse_args(args)
|
|
806
|
+
if hasattr(parsed, 'func'):
|
|
807
|
+
return parsed.func(parsed)
|
|
808
|
+
else:
|
|
809
|
+
parser.print_help()
|
|
810
|
+
return 0
|