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,422 @@
|
|
|
1
|
+
"""
|
|
2
|
+
MCP Sampling Implementation
|
|
3
|
+
|
|
4
|
+
Implements the Sampling API per MCP 2025-11-25 specification.
|
|
5
|
+
Sampling allows servers to request LLM completions from clients.
|
|
6
|
+
|
|
7
|
+
Features:
|
|
8
|
+
- Sampling requests with tool calling support
|
|
9
|
+
- Tool choice configuration
|
|
10
|
+
- Model preferences
|
|
11
|
+
- System prompt support
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import logging
|
|
15
|
+
from dataclasses import dataclass, field
|
|
16
|
+
from enum import Enum
|
|
17
|
+
from typing import Any, Callable, Dict, List, Optional
|
|
18
|
+
|
|
19
|
+
logger = logging.getLogger(__name__)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class ToolChoiceMode(str, Enum):
|
|
23
|
+
"""Tool choice modes per MCP 2025-11-25 specification."""
|
|
24
|
+
AUTO = "auto" # Model decides whether to use tools
|
|
25
|
+
NONE = "none" # Model should not use tools
|
|
26
|
+
ANY = "any" # Model must use at least one tool (any tool)
|
|
27
|
+
TOOL = "tool" # Model must use a specific tool
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
# Backwards compatibility alias
|
|
31
|
+
ToolChoiceType = ToolChoiceMode
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@dataclass
|
|
35
|
+
class ToolDefinition:
|
|
36
|
+
"""Tool definition for sampling requests."""
|
|
37
|
+
name: str
|
|
38
|
+
description: str
|
|
39
|
+
input_schema: Dict[str, Any]
|
|
40
|
+
|
|
41
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
42
|
+
return {
|
|
43
|
+
"name": self.name,
|
|
44
|
+
"description": self.description,
|
|
45
|
+
"inputSchema": self.input_schema,
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@dataclass
|
|
50
|
+
class ToolChoice:
|
|
51
|
+
"""Tool choice configuration per MCP 2025-11-25."""
|
|
52
|
+
mode: ToolChoiceMode
|
|
53
|
+
name: Optional[str] = None # Required when mode is TOOL
|
|
54
|
+
|
|
55
|
+
# Backwards compatibility alias
|
|
56
|
+
@property
|
|
57
|
+
def type(self) -> ToolChoiceMode:
|
|
58
|
+
return self.mode
|
|
59
|
+
|
|
60
|
+
@property
|
|
61
|
+
def tool_name(self) -> Optional[str]:
|
|
62
|
+
return self.name
|
|
63
|
+
|
|
64
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
65
|
+
"""Convert to MCP toolChoice format."""
|
|
66
|
+
result = {"mode": self.mode.value}
|
|
67
|
+
if self.mode == ToolChoiceMode.TOOL and self.name:
|
|
68
|
+
result["name"] = self.name
|
|
69
|
+
return result
|
|
70
|
+
|
|
71
|
+
@classmethod
|
|
72
|
+
def auto(cls) -> "ToolChoice":
|
|
73
|
+
return cls(mode=ToolChoiceMode.AUTO)
|
|
74
|
+
|
|
75
|
+
@classmethod
|
|
76
|
+
def none(cls) -> "ToolChoice":
|
|
77
|
+
return cls(mode=ToolChoiceMode.NONE)
|
|
78
|
+
|
|
79
|
+
@classmethod
|
|
80
|
+
def any(cls) -> "ToolChoice":
|
|
81
|
+
return cls(mode=ToolChoiceMode.ANY)
|
|
82
|
+
|
|
83
|
+
@classmethod
|
|
84
|
+
def tool(cls, name: str) -> "ToolChoice":
|
|
85
|
+
return cls(mode=ToolChoiceMode.TOOL, name=name)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
@dataclass
|
|
89
|
+
class SamplingMessage:
|
|
90
|
+
"""Message for sampling request."""
|
|
91
|
+
role: str # "user", "assistant", "system"
|
|
92
|
+
content: str
|
|
93
|
+
|
|
94
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
95
|
+
return {
|
|
96
|
+
"role": self.role,
|
|
97
|
+
"content": {"type": "text", "text": self.content},
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
@dataclass
|
|
102
|
+
class ModelPreferences:
|
|
103
|
+
"""Model preferences for sampling."""
|
|
104
|
+
hints: List[Dict[str, str]] = field(default_factory=list)
|
|
105
|
+
cost_priority: Optional[float] = None # 0-1, lower = prefer cheaper
|
|
106
|
+
speed_priority: Optional[float] = None # 0-1, lower = prefer faster
|
|
107
|
+
intelligence_priority: Optional[float] = None # 0-1, lower = prefer smarter
|
|
108
|
+
|
|
109
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
110
|
+
result = {}
|
|
111
|
+
if self.hints:
|
|
112
|
+
result["hints"] = self.hints
|
|
113
|
+
if self.cost_priority is not None:
|
|
114
|
+
result["costPriority"] = self.cost_priority
|
|
115
|
+
if self.speed_priority is not None:
|
|
116
|
+
result["speedPriority"] = self.speed_priority
|
|
117
|
+
if self.intelligence_priority is not None:
|
|
118
|
+
result["intelligencePriority"] = self.intelligence_priority
|
|
119
|
+
return result
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
@dataclass
|
|
123
|
+
class SamplingRequest:
|
|
124
|
+
"""
|
|
125
|
+
MCP Sampling request.
|
|
126
|
+
|
|
127
|
+
Allows servers to request LLM completions from clients.
|
|
128
|
+
"""
|
|
129
|
+
messages: List[SamplingMessage]
|
|
130
|
+
system_prompt: Optional[str] = None
|
|
131
|
+
model_preferences: Optional[ModelPreferences] = None
|
|
132
|
+
max_tokens: int = 1024
|
|
133
|
+
temperature: Optional[float] = None
|
|
134
|
+
stop_sequences: List[str] = field(default_factory=list)
|
|
135
|
+
|
|
136
|
+
# Tool calling (MCP 2025-11-25)
|
|
137
|
+
tools: List[ToolDefinition] = field(default_factory=list)
|
|
138
|
+
tool_choice: Optional[ToolChoice] = None
|
|
139
|
+
|
|
140
|
+
# Metadata
|
|
141
|
+
include_context: Optional[str] = None # "none", "thisServer", "allServers"
|
|
142
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
143
|
+
|
|
144
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
145
|
+
result = {
|
|
146
|
+
"messages": [m.to_dict() for m in self.messages],
|
|
147
|
+
"maxTokens": self.max_tokens,
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if self.system_prompt:
|
|
151
|
+
result["systemPrompt"] = self.system_prompt
|
|
152
|
+
|
|
153
|
+
if self.model_preferences:
|
|
154
|
+
result["modelPreferences"] = self.model_preferences.to_dict()
|
|
155
|
+
|
|
156
|
+
if self.temperature is not None:
|
|
157
|
+
result["temperature"] = self.temperature
|
|
158
|
+
|
|
159
|
+
if self.stop_sequences:
|
|
160
|
+
result["stopSequences"] = self.stop_sequences
|
|
161
|
+
|
|
162
|
+
# Tool calling
|
|
163
|
+
if self.tools:
|
|
164
|
+
result["tools"] = [t.to_dict() for t in self.tools]
|
|
165
|
+
|
|
166
|
+
if self.tool_choice:
|
|
167
|
+
result["toolChoice"] = self.tool_choice.to_dict()
|
|
168
|
+
|
|
169
|
+
if self.include_context:
|
|
170
|
+
result["includeContext"] = self.include_context
|
|
171
|
+
|
|
172
|
+
if self.metadata:
|
|
173
|
+
result["_meta"] = self.metadata
|
|
174
|
+
|
|
175
|
+
return result
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
@dataclass
|
|
179
|
+
class ToolCall:
|
|
180
|
+
"""Tool call from sampling response."""
|
|
181
|
+
id: str
|
|
182
|
+
name: str
|
|
183
|
+
arguments: Dict[str, Any]
|
|
184
|
+
|
|
185
|
+
@classmethod
|
|
186
|
+
def from_dict(cls, data: Dict[str, Any]) -> "ToolCall":
|
|
187
|
+
return cls(
|
|
188
|
+
id=data.get("id", ""),
|
|
189
|
+
name=data.get("name", ""),
|
|
190
|
+
arguments=data.get("arguments", {}),
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
@dataclass
|
|
195
|
+
class SamplingResponse:
|
|
196
|
+
"""
|
|
197
|
+
MCP Sampling response.
|
|
198
|
+
|
|
199
|
+
Contains the LLM completion result.
|
|
200
|
+
"""
|
|
201
|
+
role: str
|
|
202
|
+
content: str
|
|
203
|
+
model: Optional[str] = None
|
|
204
|
+
stop_reason: Optional[str] = None
|
|
205
|
+
|
|
206
|
+
# Tool calls (MCP 2025-11-25)
|
|
207
|
+
tool_calls: List[ToolCall] = field(default_factory=list)
|
|
208
|
+
|
|
209
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
210
|
+
result = {
|
|
211
|
+
"role": self.role,
|
|
212
|
+
"content": {"type": "text", "text": self.content},
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if self.model:
|
|
216
|
+
result["model"] = self.model
|
|
217
|
+
|
|
218
|
+
if self.stop_reason:
|
|
219
|
+
result["stopReason"] = self.stop_reason
|
|
220
|
+
|
|
221
|
+
if self.tool_calls:
|
|
222
|
+
result["toolCalls"] = [
|
|
223
|
+
{"id": tc.id, "name": tc.name, "arguments": tc.arguments}
|
|
224
|
+
for tc in self.tool_calls
|
|
225
|
+
]
|
|
226
|
+
|
|
227
|
+
return result
|
|
228
|
+
|
|
229
|
+
@classmethod
|
|
230
|
+
def from_dict(cls, data: Dict[str, Any]) -> "SamplingResponse":
|
|
231
|
+
content = data.get("content", {})
|
|
232
|
+
if isinstance(content, dict):
|
|
233
|
+
text = content.get("text", "")
|
|
234
|
+
else:
|
|
235
|
+
text = str(content)
|
|
236
|
+
|
|
237
|
+
tool_calls = []
|
|
238
|
+
if "toolCalls" in data:
|
|
239
|
+
tool_calls = [ToolCall.from_dict(tc) for tc in data["toolCalls"]]
|
|
240
|
+
|
|
241
|
+
return cls(
|
|
242
|
+
role=data.get("role", "assistant"),
|
|
243
|
+
content=text,
|
|
244
|
+
model=data.get("model"),
|
|
245
|
+
stop_reason=data.get("stopReason"),
|
|
246
|
+
tool_calls=tool_calls,
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
class SamplingHandler:
|
|
251
|
+
"""
|
|
252
|
+
Handles sampling requests.
|
|
253
|
+
|
|
254
|
+
Can be configured with different backends:
|
|
255
|
+
- Client callback (for MCP client-side sampling)
|
|
256
|
+
- Direct LLM integration (for server-side sampling)
|
|
257
|
+
"""
|
|
258
|
+
|
|
259
|
+
def __init__(
|
|
260
|
+
self,
|
|
261
|
+
callback: Optional[Callable] = None,
|
|
262
|
+
default_model: Optional[str] = None,
|
|
263
|
+
):
|
|
264
|
+
"""
|
|
265
|
+
Initialize sampling handler.
|
|
266
|
+
|
|
267
|
+
Args:
|
|
268
|
+
callback: Async callback for sampling requests
|
|
269
|
+
default_model: Default model to use
|
|
270
|
+
"""
|
|
271
|
+
self._callback = callback
|
|
272
|
+
self._default_model = default_model
|
|
273
|
+
|
|
274
|
+
def set_callback(self, callback: Callable) -> None:
|
|
275
|
+
"""Set the sampling callback."""
|
|
276
|
+
self._callback = callback
|
|
277
|
+
|
|
278
|
+
async def create_message(
|
|
279
|
+
self,
|
|
280
|
+
request: SamplingRequest,
|
|
281
|
+
) -> SamplingResponse:
|
|
282
|
+
"""
|
|
283
|
+
Create a sampling message.
|
|
284
|
+
|
|
285
|
+
Args:
|
|
286
|
+
request: Sampling request
|
|
287
|
+
|
|
288
|
+
Returns:
|
|
289
|
+
Sampling response
|
|
290
|
+
"""
|
|
291
|
+
if self._callback:
|
|
292
|
+
return await self._callback(request)
|
|
293
|
+
|
|
294
|
+
# Fall back to direct LLM integration
|
|
295
|
+
return await self._direct_sampling(request)
|
|
296
|
+
|
|
297
|
+
async def _direct_sampling(
|
|
298
|
+
self,
|
|
299
|
+
request: SamplingRequest,
|
|
300
|
+
) -> SamplingResponse:
|
|
301
|
+
"""
|
|
302
|
+
Direct LLM sampling using praisonaiagents.
|
|
303
|
+
|
|
304
|
+
Falls back to this when no callback is configured.
|
|
305
|
+
"""
|
|
306
|
+
try:
|
|
307
|
+
from praisonaiagents import Agent
|
|
308
|
+
|
|
309
|
+
# Build messages
|
|
310
|
+
messages = []
|
|
311
|
+
if request.system_prompt:
|
|
312
|
+
messages.append({"role": "system", "content": request.system_prompt})
|
|
313
|
+
|
|
314
|
+
for msg in request.messages:
|
|
315
|
+
messages.append({"role": msg.role, "content": msg.content})
|
|
316
|
+
|
|
317
|
+
# Create agent for sampling
|
|
318
|
+
agent = Agent(
|
|
319
|
+
instructions=request.system_prompt or "You are a helpful assistant.",
|
|
320
|
+
llm=self._default_model,
|
|
321
|
+
)
|
|
322
|
+
|
|
323
|
+
# Get last user message
|
|
324
|
+
last_message = ""
|
|
325
|
+
for msg in reversed(request.messages):
|
|
326
|
+
if msg.role == "user":
|
|
327
|
+
last_message = msg.content
|
|
328
|
+
break
|
|
329
|
+
|
|
330
|
+
# Execute
|
|
331
|
+
result = agent.chat(last_message)
|
|
332
|
+
|
|
333
|
+
return SamplingResponse(
|
|
334
|
+
role="assistant",
|
|
335
|
+
content=result,
|
|
336
|
+
model=self._default_model,
|
|
337
|
+
stop_reason="end_turn",
|
|
338
|
+
)
|
|
339
|
+
|
|
340
|
+
except ImportError:
|
|
341
|
+
return SamplingResponse(
|
|
342
|
+
role="assistant",
|
|
343
|
+
content="Sampling not available - praisonaiagents not installed",
|
|
344
|
+
stop_reason="error",
|
|
345
|
+
)
|
|
346
|
+
except Exception as e:
|
|
347
|
+
logger.exception("Sampling failed")
|
|
348
|
+
return SamplingResponse(
|
|
349
|
+
role="assistant",
|
|
350
|
+
content=f"Sampling error: {str(e)}",
|
|
351
|
+
stop_reason="error",
|
|
352
|
+
)
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
# Global sampling handler
|
|
356
|
+
_sampling_handler: Optional[SamplingHandler] = None
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
def get_sampling_handler() -> SamplingHandler:
|
|
360
|
+
"""Get the global sampling handler."""
|
|
361
|
+
global _sampling_handler
|
|
362
|
+
if _sampling_handler is None:
|
|
363
|
+
_sampling_handler = SamplingHandler()
|
|
364
|
+
return _sampling_handler
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
def set_sampling_handler(handler: SamplingHandler) -> None:
|
|
368
|
+
"""Set the global sampling handler."""
|
|
369
|
+
global _sampling_handler
|
|
370
|
+
_sampling_handler = handler
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
def create_sampling_request(
|
|
374
|
+
prompt: str,
|
|
375
|
+
system_prompt: Optional[str] = None,
|
|
376
|
+
max_tokens: int = 1024,
|
|
377
|
+
tools: Optional[List[Dict[str, Any]]] = None,
|
|
378
|
+
tool_choice: Optional[str] = None,
|
|
379
|
+
) -> SamplingRequest:
|
|
380
|
+
"""
|
|
381
|
+
Create a sampling request.
|
|
382
|
+
|
|
383
|
+
Args:
|
|
384
|
+
prompt: User prompt
|
|
385
|
+
system_prompt: System prompt
|
|
386
|
+
max_tokens: Maximum tokens
|
|
387
|
+
tools: Tool definitions
|
|
388
|
+
tool_choice: Tool choice type
|
|
389
|
+
|
|
390
|
+
Returns:
|
|
391
|
+
SamplingRequest
|
|
392
|
+
"""
|
|
393
|
+
messages = [SamplingMessage(role="user", content=prompt)]
|
|
394
|
+
|
|
395
|
+
tool_defs = []
|
|
396
|
+
if tools:
|
|
397
|
+
for tool in tools:
|
|
398
|
+
tool_defs.append(ToolDefinition(
|
|
399
|
+
name=tool.get("name", ""),
|
|
400
|
+
description=tool.get("description", ""),
|
|
401
|
+
input_schema=tool.get("inputSchema", tool.get("input_schema", {})),
|
|
402
|
+
))
|
|
403
|
+
|
|
404
|
+
tc = None
|
|
405
|
+
if tool_choice:
|
|
406
|
+
if tool_choice == "auto":
|
|
407
|
+
tc = ToolChoice.auto()
|
|
408
|
+
elif tool_choice == "none":
|
|
409
|
+
tc = ToolChoice.none()
|
|
410
|
+
elif tool_choice == "any":
|
|
411
|
+
tc = ToolChoice.any()
|
|
412
|
+
else:
|
|
413
|
+
# Specific tool name
|
|
414
|
+
tc = ToolChoice.tool(tool_choice)
|
|
415
|
+
|
|
416
|
+
return SamplingRequest(
|
|
417
|
+
messages=messages,
|
|
418
|
+
system_prompt=system_prompt,
|
|
419
|
+
max_tokens=max_tokens,
|
|
420
|
+
tools=tool_defs,
|
|
421
|
+
tool_choice=tc,
|
|
422
|
+
)
|