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,305 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Thinking Budgets CLI Feature for PraisonAI.
|
|
3
|
+
|
|
4
|
+
Provides CLI commands for managing thinking budgets.
|
|
5
|
+
|
|
6
|
+
Commands:
|
|
7
|
+
- praisonai thinking status # Show current budget
|
|
8
|
+
- praisonai thinking set <level> # Set budget level
|
|
9
|
+
- praisonai thinking stats # Show usage statistics
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import os
|
|
13
|
+
import json
|
|
14
|
+
from typing import Dict, Any
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class ThinkingHandler:
|
|
18
|
+
"""
|
|
19
|
+
Handler for thinking CLI commands.
|
|
20
|
+
|
|
21
|
+
Provides functionality to:
|
|
22
|
+
- Show current thinking budget settings
|
|
23
|
+
- Set budget levels (minimal, low, medium, high, maximum)
|
|
24
|
+
- Display usage statistics
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
CONFIG_FILE = ".praison/thinking.json"
|
|
28
|
+
|
|
29
|
+
def __init__(self, verbose: bool = False):
|
|
30
|
+
self.verbose = verbose
|
|
31
|
+
self._budget = None
|
|
32
|
+
self._tracker = None
|
|
33
|
+
|
|
34
|
+
@property
|
|
35
|
+
def feature_name(self) -> str:
|
|
36
|
+
return "thinking"
|
|
37
|
+
|
|
38
|
+
def _get_config_path(self) -> str:
|
|
39
|
+
"""Get path to config file."""
|
|
40
|
+
return os.path.join(os.getcwd(), self.CONFIG_FILE)
|
|
41
|
+
|
|
42
|
+
def _load_config(self) -> Dict[str, Any]:
|
|
43
|
+
"""Load config from file."""
|
|
44
|
+
config_path = self._get_config_path()
|
|
45
|
+
if os.path.exists(config_path):
|
|
46
|
+
try:
|
|
47
|
+
with open(config_path, 'r') as f:
|
|
48
|
+
return json.load(f)
|
|
49
|
+
except (json.JSONDecodeError, IOError):
|
|
50
|
+
pass
|
|
51
|
+
return {}
|
|
52
|
+
|
|
53
|
+
def _save_config(self, config: Dict[str, Any]):
|
|
54
|
+
"""Save config to file."""
|
|
55
|
+
config_path = self._get_config_path()
|
|
56
|
+
os.makedirs(os.path.dirname(config_path), exist_ok=True)
|
|
57
|
+
with open(config_path, 'w') as f:
|
|
58
|
+
json.dump(config, f, indent=2)
|
|
59
|
+
|
|
60
|
+
def status(self) -> Dict[str, Any]:
|
|
61
|
+
"""
|
|
62
|
+
Show current thinking budget status.
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
Current budget configuration
|
|
66
|
+
"""
|
|
67
|
+
config = self._load_config()
|
|
68
|
+
|
|
69
|
+
# Get current budget settings
|
|
70
|
+
level = config.get("level", "medium")
|
|
71
|
+
max_tokens = config.get("max_tokens", 8000)
|
|
72
|
+
adaptive = config.get("adaptive", True)
|
|
73
|
+
|
|
74
|
+
result = {
|
|
75
|
+
"level": level,
|
|
76
|
+
"max_tokens": max_tokens,
|
|
77
|
+
"adaptive": adaptive,
|
|
78
|
+
"config_file": self._get_config_path()
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
self._print_status(result)
|
|
82
|
+
return result
|
|
83
|
+
|
|
84
|
+
def _print_status(self, status: Dict[str, Any]):
|
|
85
|
+
"""Print status in formatted output."""
|
|
86
|
+
try:
|
|
87
|
+
from rich.console import Console
|
|
88
|
+
from rich.table import Table
|
|
89
|
+
from rich.panel import Panel
|
|
90
|
+
|
|
91
|
+
console = Console()
|
|
92
|
+
|
|
93
|
+
table = Table(show_header=False, box=None)
|
|
94
|
+
table.add_column("Setting", style="cyan")
|
|
95
|
+
table.add_column("Value", style="green")
|
|
96
|
+
|
|
97
|
+
table.add_row("Level", status["level"])
|
|
98
|
+
table.add_row("Max Tokens", str(status["max_tokens"]))
|
|
99
|
+
table.add_row("Adaptive", "ā" if status["adaptive"] else "ā")
|
|
100
|
+
table.add_row("Config File", status["config_file"])
|
|
101
|
+
|
|
102
|
+
console.print(Panel(table, title="Thinking Budget Status", border_style="blue"))
|
|
103
|
+
|
|
104
|
+
except ImportError:
|
|
105
|
+
print("Thinking Budget Status:")
|
|
106
|
+
print(f" Level: {status['level']}")
|
|
107
|
+
print(f" Max Tokens: {status['max_tokens']}")
|
|
108
|
+
print(f" Adaptive: {status['adaptive']}")
|
|
109
|
+
print(f" Config File: {status['config_file']}")
|
|
110
|
+
|
|
111
|
+
def set_level(self, level: str) -> Dict[str, Any]:
|
|
112
|
+
"""
|
|
113
|
+
Set thinking budget level.
|
|
114
|
+
|
|
115
|
+
Args:
|
|
116
|
+
level: Budget level (minimal, low, medium, high, maximum)
|
|
117
|
+
|
|
118
|
+
Returns:
|
|
119
|
+
Updated configuration
|
|
120
|
+
"""
|
|
121
|
+
valid_levels = ["minimal", "low", "medium", "high", "maximum"]
|
|
122
|
+
level = level.lower()
|
|
123
|
+
|
|
124
|
+
if level not in valid_levels:
|
|
125
|
+
self._print_error(f"Invalid level: {level}. Valid levels: {', '.join(valid_levels)}")
|
|
126
|
+
return {"error": f"Invalid level: {level}"}
|
|
127
|
+
|
|
128
|
+
# Get token allocation for level
|
|
129
|
+
token_map = {
|
|
130
|
+
"minimal": 2000,
|
|
131
|
+
"low": 4000,
|
|
132
|
+
"medium": 8000,
|
|
133
|
+
"high": 16000,
|
|
134
|
+
"maximum": 32000
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
config = self._load_config()
|
|
138
|
+
config["level"] = level
|
|
139
|
+
config["max_tokens"] = token_map[level]
|
|
140
|
+
self._save_config(config)
|
|
141
|
+
|
|
142
|
+
result = {
|
|
143
|
+
"level": level,
|
|
144
|
+
"max_tokens": token_map[level],
|
|
145
|
+
"message": f"Thinking budget set to {level} ({token_map[level]} tokens)"
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
self._print_success(result["message"])
|
|
149
|
+
return result
|
|
150
|
+
|
|
151
|
+
def _print_error(self, message: str):
|
|
152
|
+
"""Print error message."""
|
|
153
|
+
try:
|
|
154
|
+
from rich.console import Console
|
|
155
|
+
Console().print(f"[red]Error: {message}[/red]")
|
|
156
|
+
except ImportError:
|
|
157
|
+
print(f"Error: {message}")
|
|
158
|
+
|
|
159
|
+
def _print_success(self, message: str):
|
|
160
|
+
"""Print success message."""
|
|
161
|
+
try:
|
|
162
|
+
from rich.console import Console
|
|
163
|
+
Console().print(f"[green]ā {message}[/green]")
|
|
164
|
+
except ImportError:
|
|
165
|
+
print(f"ā {message}")
|
|
166
|
+
|
|
167
|
+
def stats(self) -> Dict[str, Any]:
|
|
168
|
+
"""
|
|
169
|
+
Show thinking usage statistics.
|
|
170
|
+
|
|
171
|
+
Returns:
|
|
172
|
+
Usage statistics
|
|
173
|
+
"""
|
|
174
|
+
config = self._load_config()
|
|
175
|
+
stats = config.get("stats", {})
|
|
176
|
+
|
|
177
|
+
result = {
|
|
178
|
+
"session_count": stats.get("session_count", 0),
|
|
179
|
+
"total_tokens_used": stats.get("total_tokens_used", 0),
|
|
180
|
+
"total_time_seconds": stats.get("total_time_seconds", 0.0),
|
|
181
|
+
"average_tokens_per_session": stats.get("average_tokens_per_session", 0.0),
|
|
182
|
+
"average_utilization": stats.get("average_utilization", 0.0),
|
|
183
|
+
"over_budget_count": stats.get("over_budget_count", 0)
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
self._print_stats(result)
|
|
187
|
+
return result
|
|
188
|
+
|
|
189
|
+
def _print_stats(self, stats: Dict[str, Any]):
|
|
190
|
+
"""Print statistics in formatted output."""
|
|
191
|
+
try:
|
|
192
|
+
from rich.console import Console
|
|
193
|
+
from rich.table import Table
|
|
194
|
+
from rich.panel import Panel
|
|
195
|
+
|
|
196
|
+
console = Console()
|
|
197
|
+
|
|
198
|
+
if stats["session_count"] == 0:
|
|
199
|
+
console.print("[yellow]No thinking sessions recorded yet.[/yellow]")
|
|
200
|
+
return
|
|
201
|
+
|
|
202
|
+
table = Table(show_header=False, box=None)
|
|
203
|
+
table.add_column("Metric", style="cyan")
|
|
204
|
+
table.add_column("Value", style="green")
|
|
205
|
+
|
|
206
|
+
table.add_row("Sessions", str(stats["session_count"]))
|
|
207
|
+
table.add_row("Total Tokens Used", f"{stats['total_tokens_used']:,}")
|
|
208
|
+
table.add_row("Total Time", f"{stats['total_time_seconds']:.1f}s")
|
|
209
|
+
table.add_row("Avg Tokens/Session", f"{stats['average_tokens_per_session']:.0f}")
|
|
210
|
+
table.add_row("Avg Utilization", f"{stats['average_utilization']:.1%}")
|
|
211
|
+
table.add_row("Over Budget", str(stats["over_budget_count"]))
|
|
212
|
+
|
|
213
|
+
console.print(Panel(table, title="Thinking Usage Statistics", border_style="blue"))
|
|
214
|
+
|
|
215
|
+
except ImportError:
|
|
216
|
+
print("Thinking Usage Statistics:")
|
|
217
|
+
print(f" Sessions: {stats['session_count']}")
|
|
218
|
+
print(f" Total Tokens Used: {stats['total_tokens_used']:,}")
|
|
219
|
+
print(f" Total Time: {stats['total_time_seconds']:.1f}s")
|
|
220
|
+
print(f" Avg Tokens/Session: {stats['average_tokens_per_session']:.0f}")
|
|
221
|
+
print(f" Avg Utilization: {stats['average_utilization']:.1%}")
|
|
222
|
+
print(f" Over Budget: {stats['over_budget_count']}")
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def handle_thinking_command(args: list) -> int:
|
|
226
|
+
"""
|
|
227
|
+
Handle thinking CLI commands.
|
|
228
|
+
|
|
229
|
+
Args:
|
|
230
|
+
args: Command arguments
|
|
231
|
+
|
|
232
|
+
Returns:
|
|
233
|
+
Exit code (0 for success)
|
|
234
|
+
"""
|
|
235
|
+
if not args:
|
|
236
|
+
args = ["status"]
|
|
237
|
+
|
|
238
|
+
command = args[0].lower()
|
|
239
|
+
handler = ThinkingHandler()
|
|
240
|
+
|
|
241
|
+
if command == "status":
|
|
242
|
+
handler.status()
|
|
243
|
+
return 0
|
|
244
|
+
|
|
245
|
+
elif command == "set":
|
|
246
|
+
if len(args) < 2:
|
|
247
|
+
handler._print_error("Usage: praisonai thinking set <level>")
|
|
248
|
+
print("Levels: minimal, low, medium, high, maximum")
|
|
249
|
+
return 1
|
|
250
|
+
result = handler.set_level(args[1])
|
|
251
|
+
return 0 if "error" not in result else 1
|
|
252
|
+
|
|
253
|
+
elif command == "stats":
|
|
254
|
+
handler.stats()
|
|
255
|
+
return 0
|
|
256
|
+
|
|
257
|
+
elif command == "help":
|
|
258
|
+
_print_help()
|
|
259
|
+
return 0
|
|
260
|
+
|
|
261
|
+
else:
|
|
262
|
+
handler._print_error(f"Unknown command: {command}")
|
|
263
|
+
_print_help()
|
|
264
|
+
return 1
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
def _print_help():
|
|
268
|
+
"""Print help message."""
|
|
269
|
+
try:
|
|
270
|
+
from rich.console import Console
|
|
271
|
+
from rich.panel import Panel
|
|
272
|
+
|
|
273
|
+
console = Console()
|
|
274
|
+
help_text = """
|
|
275
|
+
[bold]Thinking Budget Commands[/bold]
|
|
276
|
+
|
|
277
|
+
[cyan]praisonai thinking status[/cyan]
|
|
278
|
+
Show current thinking budget settings
|
|
279
|
+
|
|
280
|
+
[cyan]praisonai thinking set <level>[/cyan]
|
|
281
|
+
Set budget level (minimal, low, medium, high, maximum)
|
|
282
|
+
|
|
283
|
+
Levels:
|
|
284
|
+
⢠minimal - 2,000 tokens
|
|
285
|
+
⢠low - 4,000 tokens
|
|
286
|
+
⢠medium - 8,000 tokens (default)
|
|
287
|
+
⢠high - 16,000 tokens
|
|
288
|
+
⢠maximum - 32,000 tokens
|
|
289
|
+
|
|
290
|
+
[cyan]praisonai thinking stats[/cyan]
|
|
291
|
+
Show usage statistics
|
|
292
|
+
|
|
293
|
+
[cyan]praisonai thinking help[/cyan]
|
|
294
|
+
Show this help message
|
|
295
|
+
"""
|
|
296
|
+
console.print(Panel(help_text, title="Thinking Budget Help", border_style="blue"))
|
|
297
|
+
|
|
298
|
+
except ImportError:
|
|
299
|
+
print("Thinking Budget Commands:")
|
|
300
|
+
print(" praisonai thinking status - Show current settings")
|
|
301
|
+
print(" praisonai thinking set <level> - Set budget level")
|
|
302
|
+
print(" praisonai thinking stats - Show usage statistics")
|
|
303
|
+
print(" praisonai thinking help - Show this help")
|
|
304
|
+
print("")
|
|
305
|
+
print("Levels: minimal (2K), low (4K), medium (8K), high (16K), maximum (32K)")
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Todo Handler for CLI.
|
|
3
|
+
|
|
4
|
+
Provides todo list management.
|
|
5
|
+
Usage: praisonai todo list
|
|
6
|
+
praisonai todo add "New task"
|
|
7
|
+
praisonai "Plan project" --todo
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import os
|
|
11
|
+
import json
|
|
12
|
+
from typing import Any, Dict, List
|
|
13
|
+
from .base import CommandHandler, FlagHandler
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class TodoHandler(CommandHandler, FlagHandler):
|
|
17
|
+
"""
|
|
18
|
+
Handler for todo command and --todo flag.
|
|
19
|
+
|
|
20
|
+
Manages todo lists for task planning.
|
|
21
|
+
|
|
22
|
+
Example:
|
|
23
|
+
praisonai todo list
|
|
24
|
+
praisonai todo add "Implement feature X"
|
|
25
|
+
praisonai todo complete 1
|
|
26
|
+
praisonai "Plan project" --todo
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
def __init__(self, verbose: bool = False, workspace: str = None):
|
|
30
|
+
CommandHandler.__init__(self, verbose)
|
|
31
|
+
self.workspace = workspace or os.path.join(os.path.expanduser("~"), ".praison")
|
|
32
|
+
self.todo_file = os.path.join(self.workspace, "todos.json")
|
|
33
|
+
os.makedirs(self.workspace, exist_ok=True)
|
|
34
|
+
self._todos = None
|
|
35
|
+
|
|
36
|
+
@property
|
|
37
|
+
def feature_name(self) -> str:
|
|
38
|
+
return "todo"
|
|
39
|
+
|
|
40
|
+
@property
|
|
41
|
+
def flag_name(self) -> str:
|
|
42
|
+
return "todo"
|
|
43
|
+
|
|
44
|
+
@property
|
|
45
|
+
def flag_help(self) -> str:
|
|
46
|
+
return "Generate todo list from task"
|
|
47
|
+
|
|
48
|
+
def get_actions(self) -> List[str]:
|
|
49
|
+
return ["list", "add", "complete", "delete", "clear", "help"]
|
|
50
|
+
|
|
51
|
+
def get_help_text(self) -> str:
|
|
52
|
+
return """
|
|
53
|
+
Todo Commands:
|
|
54
|
+
praisonai todo list - List all todos
|
|
55
|
+
praisonai todo add <task> - Add a new todo
|
|
56
|
+
praisonai todo complete <id> - Mark todo as complete
|
|
57
|
+
praisonai todo delete <id> - Delete a todo
|
|
58
|
+
praisonai todo clear - Clear all todos
|
|
59
|
+
|
|
60
|
+
Flag Usage:
|
|
61
|
+
praisonai "Plan project" --todo - Generate todos from task
|
|
62
|
+
"""
|
|
63
|
+
|
|
64
|
+
def _load_todos(self) -> List[Dict[str, Any]]:
|
|
65
|
+
"""Load todos from file."""
|
|
66
|
+
if self._todos is not None:
|
|
67
|
+
return self._todos
|
|
68
|
+
|
|
69
|
+
if os.path.exists(self.todo_file):
|
|
70
|
+
try:
|
|
71
|
+
with open(self.todo_file, 'r') as f:
|
|
72
|
+
self._todos = json.load(f)
|
|
73
|
+
except Exception:
|
|
74
|
+
self._todos = []
|
|
75
|
+
else:
|
|
76
|
+
self._todos = []
|
|
77
|
+
|
|
78
|
+
return self._todos
|
|
79
|
+
|
|
80
|
+
def _save_todos(self):
|
|
81
|
+
"""Save todos to file."""
|
|
82
|
+
try:
|
|
83
|
+
with open(self.todo_file, 'w') as f:
|
|
84
|
+
json.dump(self._todos or [], f, indent=2)
|
|
85
|
+
except Exception as e:
|
|
86
|
+
self.log(f"Failed to save todos: {e}", "error")
|
|
87
|
+
|
|
88
|
+
def action_list(self, args: List[str], **kwargs) -> List[Dict[str, Any]]:
|
|
89
|
+
"""
|
|
90
|
+
List all todos.
|
|
91
|
+
|
|
92
|
+
Returns:
|
|
93
|
+
List of todo items
|
|
94
|
+
"""
|
|
95
|
+
todos = self._load_todos()
|
|
96
|
+
|
|
97
|
+
if not todos:
|
|
98
|
+
self.print_status("š No todos found", "info")
|
|
99
|
+
return []
|
|
100
|
+
|
|
101
|
+
self.print_status("\nš Todo List:", "info")
|
|
102
|
+
self.print_status("-" * 50, "info")
|
|
103
|
+
|
|
104
|
+
for i, todo in enumerate(todos, 1):
|
|
105
|
+
status = "ā
" if todo.get('completed') else "ā¬"
|
|
106
|
+
task = todo.get('task', 'Unknown')
|
|
107
|
+
priority = todo.get('priority', 'medium')
|
|
108
|
+
|
|
109
|
+
priority_color = {
|
|
110
|
+
'high': 'š“',
|
|
111
|
+
'medium': 'š”',
|
|
112
|
+
'low': 'š¢'
|
|
113
|
+
}.get(priority, 'āŖ')
|
|
114
|
+
|
|
115
|
+
self.print_status(f" {i}. {status} {priority_color} {task}", "info")
|
|
116
|
+
|
|
117
|
+
self.print_status("-" * 50, "info")
|
|
118
|
+
completed = sum(1 for t in todos if t.get('completed'))
|
|
119
|
+
self.print_status(f" {completed}/{len(todos)} completed", "info")
|
|
120
|
+
|
|
121
|
+
return todos
|
|
122
|
+
|
|
123
|
+
def action_add(self, args: List[str], **kwargs) -> Dict[str, Any]:
|
|
124
|
+
"""
|
|
125
|
+
Add a new todo.
|
|
126
|
+
|
|
127
|
+
Args:
|
|
128
|
+
args: List containing task description
|
|
129
|
+
|
|
130
|
+
Returns:
|
|
131
|
+
Created todo item
|
|
132
|
+
"""
|
|
133
|
+
if not args:
|
|
134
|
+
self.print_status("Usage: praisonai todo add <task>", "error")
|
|
135
|
+
return {}
|
|
136
|
+
|
|
137
|
+
task = ' '.join(args)
|
|
138
|
+
priority = kwargs.get('priority', 'medium')
|
|
139
|
+
|
|
140
|
+
todos = self._load_todos()
|
|
141
|
+
|
|
142
|
+
todo = {
|
|
143
|
+
'id': len(todos) + 1,
|
|
144
|
+
'task': task,
|
|
145
|
+
'completed': False,
|
|
146
|
+
'priority': priority,
|
|
147
|
+
'created_at': self._get_timestamp()
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
todos.append(todo)
|
|
151
|
+
self._todos = todos
|
|
152
|
+
self._save_todos()
|
|
153
|
+
|
|
154
|
+
self.print_status(f"ā
Added: {task}", "success")
|
|
155
|
+
return todo
|
|
156
|
+
|
|
157
|
+
def action_complete(self, args: List[str], **kwargs) -> bool:
|
|
158
|
+
"""
|
|
159
|
+
Mark a todo as complete.
|
|
160
|
+
|
|
161
|
+
Args:
|
|
162
|
+
args: List containing todo ID
|
|
163
|
+
|
|
164
|
+
Returns:
|
|
165
|
+
True if successful
|
|
166
|
+
"""
|
|
167
|
+
if not args:
|
|
168
|
+
self.print_status("Usage: praisonai todo complete <id>", "error")
|
|
169
|
+
return False
|
|
170
|
+
|
|
171
|
+
try:
|
|
172
|
+
todo_id = int(args[0])
|
|
173
|
+
except ValueError:
|
|
174
|
+
self.print_status("Invalid todo ID", "error")
|
|
175
|
+
return False
|
|
176
|
+
|
|
177
|
+
todos = self._load_todos()
|
|
178
|
+
|
|
179
|
+
if todo_id < 1 or todo_id > len(todos):
|
|
180
|
+
self.print_status(f"Todo {todo_id} not found", "error")
|
|
181
|
+
return False
|
|
182
|
+
|
|
183
|
+
todos[todo_id - 1]['completed'] = True
|
|
184
|
+
todos[todo_id - 1]['completed_at'] = self._get_timestamp()
|
|
185
|
+
self._todos = todos
|
|
186
|
+
self._save_todos()
|
|
187
|
+
|
|
188
|
+
self.print_status(f"ā
Completed: {todos[todo_id - 1]['task']}", "success")
|
|
189
|
+
return True
|
|
190
|
+
|
|
191
|
+
def action_delete(self, args: List[str], **kwargs) -> bool:
|
|
192
|
+
"""
|
|
193
|
+
Delete a todo.
|
|
194
|
+
|
|
195
|
+
Args:
|
|
196
|
+
args: List containing todo ID
|
|
197
|
+
|
|
198
|
+
Returns:
|
|
199
|
+
True if successful
|
|
200
|
+
"""
|
|
201
|
+
if not args:
|
|
202
|
+
self.print_status("Usage: praisonai todo delete <id>", "error")
|
|
203
|
+
return False
|
|
204
|
+
|
|
205
|
+
try:
|
|
206
|
+
todo_id = int(args[0])
|
|
207
|
+
except ValueError:
|
|
208
|
+
self.print_status("Invalid todo ID", "error")
|
|
209
|
+
return False
|
|
210
|
+
|
|
211
|
+
todos = self._load_todos()
|
|
212
|
+
|
|
213
|
+
if todo_id < 1 or todo_id > len(todos):
|
|
214
|
+
self.print_status(f"Todo {todo_id} not found", "error")
|
|
215
|
+
return False
|
|
216
|
+
|
|
217
|
+
deleted = todos.pop(todo_id - 1)
|
|
218
|
+
self._todos = todos
|
|
219
|
+
self._save_todos()
|
|
220
|
+
|
|
221
|
+
self.print_status(f"šļø Deleted: {deleted['task']}", "success")
|
|
222
|
+
return True
|
|
223
|
+
|
|
224
|
+
def action_clear(self, args: List[str], **kwargs) -> bool:
|
|
225
|
+
"""
|
|
226
|
+
Clear all todos.
|
|
227
|
+
|
|
228
|
+
Returns:
|
|
229
|
+
True if successful
|
|
230
|
+
"""
|
|
231
|
+
self._todos = []
|
|
232
|
+
self._save_todos()
|
|
233
|
+
self.print_status("šļø All todos cleared", "success")
|
|
234
|
+
return True
|
|
235
|
+
|
|
236
|
+
def _get_timestamp(self) -> str:
|
|
237
|
+
"""Get current timestamp."""
|
|
238
|
+
from datetime import datetime
|
|
239
|
+
return datetime.now().isoformat()
|
|
240
|
+
|
|
241
|
+
def apply_to_agent_config(self, config: Dict[str, Any], flag_value: Any) -> Dict[str, Any]:
|
|
242
|
+
"""
|
|
243
|
+
Apply todo configuration.
|
|
244
|
+
|
|
245
|
+
Args:
|
|
246
|
+
config: Agent configuration dictionary
|
|
247
|
+
flag_value: Boolean indicating todo generation
|
|
248
|
+
|
|
249
|
+
Returns:
|
|
250
|
+
Modified configuration
|
|
251
|
+
"""
|
|
252
|
+
if flag_value:
|
|
253
|
+
config['generate_todos'] = True
|
|
254
|
+
return config
|
|
255
|
+
|
|
256
|
+
def generate_todos_from_response(self, response: str) -> List[Dict[str, Any]]:
|
|
257
|
+
"""
|
|
258
|
+
Extract todos from agent response.
|
|
259
|
+
|
|
260
|
+
Args:
|
|
261
|
+
response: Agent response text
|
|
262
|
+
|
|
263
|
+
Returns:
|
|
264
|
+
List of extracted todos
|
|
265
|
+
"""
|
|
266
|
+
# Simple extraction - look for numbered lists or bullet points
|
|
267
|
+
import re
|
|
268
|
+
|
|
269
|
+
todos = []
|
|
270
|
+
lines = response.split('\n')
|
|
271
|
+
|
|
272
|
+
for line in lines:
|
|
273
|
+
line = line.strip()
|
|
274
|
+
# Match numbered lists (1. Task, 1) Task)
|
|
275
|
+
match = re.match(r'^[\d]+[\.\)]\s*(.+)$', line)
|
|
276
|
+
if match:
|
|
277
|
+
task = match.group(1).strip()
|
|
278
|
+
if task and len(task) > 3:
|
|
279
|
+
todos.append({
|
|
280
|
+
'task': task,
|
|
281
|
+
'completed': False,
|
|
282
|
+
'priority': 'medium'
|
|
283
|
+
})
|
|
284
|
+
# Match bullet points (- Task, * Task, ⢠Task)
|
|
285
|
+
elif line.startswith(('-', '*', 'ā¢', 'ā')):
|
|
286
|
+
task = line[1:].strip()
|
|
287
|
+
if task and len(task) > 3:
|
|
288
|
+
todos.append({
|
|
289
|
+
'task': task,
|
|
290
|
+
'completed': False,
|
|
291
|
+
'priority': 'medium'
|
|
292
|
+
})
|
|
293
|
+
|
|
294
|
+
return todos
|
|
295
|
+
|
|
296
|
+
def post_process_result(self, result: Any, flag_value: Any) -> Any:
|
|
297
|
+
"""
|
|
298
|
+
Post-process result to extract todos.
|
|
299
|
+
|
|
300
|
+
Args:
|
|
301
|
+
result: Agent output
|
|
302
|
+
flag_value: Boolean indicating todo generation
|
|
303
|
+
|
|
304
|
+
Returns:
|
|
305
|
+
Original result (todos are saved)
|
|
306
|
+
"""
|
|
307
|
+
if not flag_value:
|
|
308
|
+
return result
|
|
309
|
+
|
|
310
|
+
extracted = self.generate_todos_from_response(str(result))
|
|
311
|
+
|
|
312
|
+
if extracted:
|
|
313
|
+
todos = self._load_todos()
|
|
314
|
+
for todo in extracted:
|
|
315
|
+
todo['id'] = len(todos) + 1
|
|
316
|
+
todo['created_at'] = self._get_timestamp()
|
|
317
|
+
todos.append(todo)
|
|
318
|
+
|
|
319
|
+
self._todos = todos
|
|
320
|
+
self._save_todos()
|
|
321
|
+
|
|
322
|
+
self.print_status(f"\nš Generated {len(extracted)} todos:", "success")
|
|
323
|
+
for todo in extracted:
|
|
324
|
+
self.print_status(f" ⢠{todo['task']}", "info")
|
|
325
|
+
|
|
326
|
+
return result
|
|
327
|
+
|
|
328
|
+
def execute(self, action: str = None, action_args: List[str] = None, **kwargs) -> Any:
|
|
329
|
+
"""Execute todo command action."""
|
|
330
|
+
if action is None:
|
|
331
|
+
action = "list"
|
|
332
|
+
if action_args is None:
|
|
333
|
+
action_args = []
|
|
334
|
+
return CommandHandler.execute(self, action, action_args, **kwargs)
|