atlas-chat 0.1.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.
- atlas/__init__.py +40 -0
- atlas/application/__init__.py +7 -0
- atlas/application/chat/__init__.py +7 -0
- atlas/application/chat/agent/__init__.py +10 -0
- atlas/application/chat/agent/act_loop.py +179 -0
- atlas/application/chat/agent/factory.py +142 -0
- atlas/application/chat/agent/protocols.py +46 -0
- atlas/application/chat/agent/react_loop.py +338 -0
- atlas/application/chat/agent/think_act_loop.py +171 -0
- atlas/application/chat/approval_manager.py +151 -0
- atlas/application/chat/elicitation_manager.py +191 -0
- atlas/application/chat/events/__init__.py +1 -0
- atlas/application/chat/events/agent_event_relay.py +112 -0
- atlas/application/chat/modes/__init__.py +1 -0
- atlas/application/chat/modes/agent.py +125 -0
- atlas/application/chat/modes/plain.py +74 -0
- atlas/application/chat/modes/rag.py +81 -0
- atlas/application/chat/modes/tools.py +179 -0
- atlas/application/chat/orchestrator.py +213 -0
- atlas/application/chat/policies/__init__.py +1 -0
- atlas/application/chat/policies/tool_authorization.py +99 -0
- atlas/application/chat/preprocessors/__init__.py +1 -0
- atlas/application/chat/preprocessors/message_builder.py +92 -0
- atlas/application/chat/preprocessors/prompt_override_service.py +104 -0
- atlas/application/chat/service.py +454 -0
- atlas/application/chat/utilities/__init__.py +6 -0
- atlas/application/chat/utilities/error_handler.py +367 -0
- atlas/application/chat/utilities/event_notifier.py +546 -0
- atlas/application/chat/utilities/file_processor.py +613 -0
- atlas/application/chat/utilities/tool_executor.py +789 -0
- atlas/atlas_chat_cli.py +347 -0
- atlas/atlas_client.py +238 -0
- atlas/core/__init__.py +0 -0
- atlas/core/auth.py +205 -0
- atlas/core/authorization_manager.py +27 -0
- atlas/core/capabilities.py +123 -0
- atlas/core/compliance.py +215 -0
- atlas/core/domain_whitelist.py +147 -0
- atlas/core/domain_whitelist_middleware.py +82 -0
- atlas/core/http_client.py +28 -0
- atlas/core/log_sanitizer.py +102 -0
- atlas/core/metrics_logger.py +59 -0
- atlas/core/middleware.py +131 -0
- atlas/core/otel_config.py +242 -0
- atlas/core/prompt_risk.py +200 -0
- atlas/core/rate_limit.py +0 -0
- atlas/core/rate_limit_middleware.py +64 -0
- atlas/core/security_headers_middleware.py +51 -0
- atlas/domain/__init__.py +37 -0
- atlas/domain/chat/__init__.py +1 -0
- atlas/domain/chat/dtos.py +85 -0
- atlas/domain/errors.py +96 -0
- atlas/domain/messages/__init__.py +12 -0
- atlas/domain/messages/models.py +160 -0
- atlas/domain/rag_mcp_service.py +664 -0
- atlas/domain/sessions/__init__.py +7 -0
- atlas/domain/sessions/models.py +36 -0
- atlas/domain/unified_rag_service.py +371 -0
- atlas/infrastructure/__init__.py +10 -0
- atlas/infrastructure/app_factory.py +135 -0
- atlas/infrastructure/events/__init__.py +1 -0
- atlas/infrastructure/events/cli_event_publisher.py +140 -0
- atlas/infrastructure/events/websocket_publisher.py +140 -0
- atlas/infrastructure/sessions/in_memory_repository.py +56 -0
- atlas/infrastructure/transport/__init__.py +7 -0
- atlas/infrastructure/transport/websocket_connection_adapter.py +33 -0
- atlas/init_cli.py +226 -0
- atlas/interfaces/__init__.py +15 -0
- atlas/interfaces/events.py +134 -0
- atlas/interfaces/llm.py +54 -0
- atlas/interfaces/rag.py +40 -0
- atlas/interfaces/sessions.py +75 -0
- atlas/interfaces/tools.py +57 -0
- atlas/interfaces/transport.py +24 -0
- atlas/main.py +564 -0
- atlas/mcp/api_key_demo/README.md +76 -0
- atlas/mcp/api_key_demo/main.py +172 -0
- atlas/mcp/api_key_demo/run.sh +56 -0
- atlas/mcp/basictable/main.py +147 -0
- atlas/mcp/calculator/main.py +149 -0
- atlas/mcp/code-executor/execution_engine.py +98 -0
- atlas/mcp/code-executor/execution_environment.py +95 -0
- atlas/mcp/code-executor/main.py +528 -0
- atlas/mcp/code-executor/result_processing.py +276 -0
- atlas/mcp/code-executor/script_generation.py +195 -0
- atlas/mcp/code-executor/security_checker.py +140 -0
- atlas/mcp/corporate_cars/main.py +437 -0
- atlas/mcp/csv_reporter/main.py +545 -0
- atlas/mcp/duckduckgo/main.py +182 -0
- atlas/mcp/elicitation_demo/README.md +171 -0
- atlas/mcp/elicitation_demo/main.py +262 -0
- atlas/mcp/env-demo/README.md +158 -0
- atlas/mcp/env-demo/main.py +199 -0
- atlas/mcp/file_size_test/main.py +284 -0
- atlas/mcp/filesystem/main.py +348 -0
- atlas/mcp/image_demo/main.py +113 -0
- atlas/mcp/image_demo/requirements.txt +4 -0
- atlas/mcp/logging_demo/README.md +72 -0
- atlas/mcp/logging_demo/main.py +103 -0
- atlas/mcp/many_tools_demo/main.py +50 -0
- atlas/mcp/order_database/__init__.py +0 -0
- atlas/mcp/order_database/main.py +369 -0
- atlas/mcp/order_database/signal_data.csv +1001 -0
- atlas/mcp/pdfbasic/main.py +394 -0
- atlas/mcp/pptx_generator/main.py +760 -0
- atlas/mcp/pptx_generator/requirements.txt +13 -0
- atlas/mcp/pptx_generator/run_test.sh +1 -0
- atlas/mcp/pptx_generator/test_pptx_generator_security.py +169 -0
- atlas/mcp/progress_demo/main.py +167 -0
- atlas/mcp/progress_updates_demo/QUICKSTART.md +273 -0
- atlas/mcp/progress_updates_demo/README.md +120 -0
- atlas/mcp/progress_updates_demo/main.py +497 -0
- atlas/mcp/prompts/main.py +222 -0
- atlas/mcp/public_demo/main.py +189 -0
- atlas/mcp/sampling_demo/README.md +169 -0
- atlas/mcp/sampling_demo/main.py +234 -0
- atlas/mcp/thinking/main.py +77 -0
- atlas/mcp/tool_planner/main.py +240 -0
- atlas/mcp/ui-demo/badmesh.png +0 -0
- atlas/mcp/ui-demo/main.py +383 -0
- atlas/mcp/ui-demo/templates/button_demo.html +32 -0
- atlas/mcp/ui-demo/templates/data_visualization.html +32 -0
- atlas/mcp/ui-demo/templates/form_demo.html +28 -0
- atlas/mcp/username-override-demo/README.md +320 -0
- atlas/mcp/username-override-demo/main.py +308 -0
- atlas/modules/__init__.py +0 -0
- atlas/modules/config/__init__.py +34 -0
- atlas/modules/config/cli.py +231 -0
- atlas/modules/config/config_manager.py +1096 -0
- atlas/modules/file_storage/__init__.py +22 -0
- atlas/modules/file_storage/cli.py +330 -0
- atlas/modules/file_storage/content_extractor.py +290 -0
- atlas/modules/file_storage/manager.py +295 -0
- atlas/modules/file_storage/mock_s3_client.py +402 -0
- atlas/modules/file_storage/s3_client.py +417 -0
- atlas/modules/llm/__init__.py +19 -0
- atlas/modules/llm/caller.py +287 -0
- atlas/modules/llm/litellm_caller.py +675 -0
- atlas/modules/llm/models.py +19 -0
- atlas/modules/mcp_tools/__init__.py +17 -0
- atlas/modules/mcp_tools/client.py +2123 -0
- atlas/modules/mcp_tools/token_storage.py +556 -0
- atlas/modules/prompts/prompt_provider.py +130 -0
- atlas/modules/rag/__init__.py +24 -0
- atlas/modules/rag/atlas_rag_client.py +336 -0
- atlas/modules/rag/client.py +129 -0
- atlas/routes/admin_routes.py +865 -0
- atlas/routes/config_routes.py +484 -0
- atlas/routes/feedback_routes.py +361 -0
- atlas/routes/files_routes.py +274 -0
- atlas/routes/health_routes.py +40 -0
- atlas/routes/mcp_auth_routes.py +223 -0
- atlas/server_cli.py +164 -0
- atlas/tests/conftest.py +20 -0
- atlas/tests/integration/test_mcp_auth_integration.py +152 -0
- atlas/tests/manual_test_sampling.py +87 -0
- atlas/tests/modules/mcp_tools/test_client_auth.py +226 -0
- atlas/tests/modules/mcp_tools/test_client_env.py +191 -0
- atlas/tests/test_admin_mcp_server_management_routes.py +141 -0
- atlas/tests/test_agent_roa.py +135 -0
- atlas/tests/test_app_factory_smoke.py +47 -0
- atlas/tests/test_approval_manager.py +439 -0
- atlas/tests/test_atlas_client.py +188 -0
- atlas/tests/test_atlas_rag_client.py +447 -0
- atlas/tests/test_atlas_rag_integration.py +224 -0
- atlas/tests/test_attach_file_flow.py +287 -0
- atlas/tests/test_auth_utils.py +165 -0
- atlas/tests/test_backend_public_url.py +185 -0
- atlas/tests/test_banner_logging.py +287 -0
- atlas/tests/test_capability_tokens_and_injection.py +203 -0
- atlas/tests/test_compliance_level.py +54 -0
- atlas/tests/test_compliance_manager.py +253 -0
- atlas/tests/test_config_manager.py +617 -0
- atlas/tests/test_config_manager_paths.py +12 -0
- atlas/tests/test_core_auth.py +18 -0
- atlas/tests/test_core_utils.py +190 -0
- atlas/tests/test_docker_env_sync.py +202 -0
- atlas/tests/test_domain_errors.py +329 -0
- atlas/tests/test_domain_whitelist.py +359 -0
- atlas/tests/test_elicitation_manager.py +408 -0
- atlas/tests/test_elicitation_routing.py +296 -0
- atlas/tests/test_env_demo_server.py +88 -0
- atlas/tests/test_error_classification.py +113 -0
- atlas/tests/test_error_flow_integration.py +116 -0
- atlas/tests/test_feedback_routes.py +333 -0
- atlas/tests/test_file_content_extraction.py +1134 -0
- atlas/tests/test_file_extraction_routes.py +158 -0
- atlas/tests/test_file_library.py +107 -0
- atlas/tests/test_file_manager_unit.py +18 -0
- atlas/tests/test_health_route.py +49 -0
- atlas/tests/test_http_client_stub.py +8 -0
- atlas/tests/test_imports_smoke.py +30 -0
- atlas/tests/test_interfaces_llm_response.py +9 -0
- atlas/tests/test_issue_access_denied_fix.py +136 -0
- atlas/tests/test_llm_env_expansion.py +836 -0
- atlas/tests/test_log_level_sensitive_data.py +285 -0
- atlas/tests/test_mcp_auth_routes.py +341 -0
- atlas/tests/test_mcp_client_auth.py +331 -0
- atlas/tests/test_mcp_data_injection.py +270 -0
- atlas/tests/test_mcp_get_authorized_servers.py +95 -0
- atlas/tests/test_mcp_hot_reload.py +512 -0
- atlas/tests/test_mcp_image_content.py +424 -0
- atlas/tests/test_mcp_logging.py +172 -0
- atlas/tests/test_mcp_progress_updates.py +313 -0
- atlas/tests/test_mcp_prompt_override_system_prompt.py +102 -0
- atlas/tests/test_mcp_prompts_server.py +39 -0
- atlas/tests/test_mcp_tool_result_parsing.py +296 -0
- atlas/tests/test_metrics_logger.py +56 -0
- atlas/tests/test_middleware_auth.py +379 -0
- atlas/tests/test_prompt_risk_and_acl.py +141 -0
- atlas/tests/test_rag_mcp_aggregator.py +204 -0
- atlas/tests/test_rag_mcp_service.py +224 -0
- atlas/tests/test_rate_limit_middleware.py +45 -0
- atlas/tests/test_routes_config_smoke.py +60 -0
- atlas/tests/test_routes_files_download_token.py +41 -0
- atlas/tests/test_routes_files_health.py +18 -0
- atlas/tests/test_runtime_imports.py +53 -0
- atlas/tests/test_sampling_integration.py +482 -0
- atlas/tests/test_security_admin_routes.py +61 -0
- atlas/tests/test_security_capability_tokens.py +65 -0
- atlas/tests/test_security_file_stats_scope.py +21 -0
- atlas/tests/test_security_header_injection.py +191 -0
- atlas/tests/test_security_headers_and_filename.py +63 -0
- atlas/tests/test_shared_session_repository.py +101 -0
- atlas/tests/test_system_prompt_loading.py +181 -0
- atlas/tests/test_token_storage.py +505 -0
- atlas/tests/test_tool_approval_config.py +93 -0
- atlas/tests/test_tool_approval_utils.py +356 -0
- atlas/tests/test_tool_authorization_group_filtering.py +223 -0
- atlas/tests/test_tool_details_in_config.py +108 -0
- atlas/tests/test_tool_planner.py +300 -0
- atlas/tests/test_unified_rag_service.py +398 -0
- atlas/tests/test_username_override_in_approval.py +258 -0
- atlas/tests/test_websocket_auth_header.py +168 -0
- atlas/version.py +6 -0
- atlas_chat-0.1.0.data/data/.env.example +253 -0
- atlas_chat-0.1.0.data/data/config/defaults/compliance-levels.json +44 -0
- atlas_chat-0.1.0.data/data/config/defaults/domain-whitelist.json +123 -0
- atlas_chat-0.1.0.data/data/config/defaults/file-extractors.json +74 -0
- atlas_chat-0.1.0.data/data/config/defaults/help-config.json +198 -0
- atlas_chat-0.1.0.data/data/config/defaults/llmconfig-buggy.yml +11 -0
- atlas_chat-0.1.0.data/data/config/defaults/llmconfig.yml +19 -0
- atlas_chat-0.1.0.data/data/config/defaults/mcp.json +138 -0
- atlas_chat-0.1.0.data/data/config/defaults/rag-sources.json +17 -0
- atlas_chat-0.1.0.data/data/config/defaults/splash-config.json +16 -0
- atlas_chat-0.1.0.dist-info/METADATA +236 -0
- atlas_chat-0.1.0.dist-info/RECORD +250 -0
- atlas_chat-0.1.0.dist-info/WHEEL +5 -0
- atlas_chat-0.1.0.dist-info/entry_points.txt +4 -0
- atlas_chat-0.1.0.dist-info/top_level.txt +1 -0
atlas/domain/errors.py
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"""Domain-level errors and exceptions."""
|
|
2
|
+
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class DomainError(Exception):
|
|
7
|
+
"""Base domain error."""
|
|
8
|
+
def __init__(self, message: str, code: Optional[str] = None):
|
|
9
|
+
super().__init__(message)
|
|
10
|
+
self.message = message
|
|
11
|
+
self.code = code
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class ValidationError(DomainError):
|
|
15
|
+
"""Validation error."""
|
|
16
|
+
pass
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class SessionError(DomainError):
|
|
20
|
+
"""Session-related error."""
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class MessageError(DomainError):
|
|
25
|
+
"""Message-related error."""
|
|
26
|
+
pass
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class AuthenticationError(DomainError):
|
|
30
|
+
"""Authentication error."""
|
|
31
|
+
pass
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class AuthorizationError(DomainError):
|
|
35
|
+
"""Authorization error."""
|
|
36
|
+
pass
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class ConfigurationError(DomainError):
|
|
40
|
+
"""Configuration error."""
|
|
41
|
+
pass
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class LLMError(DomainError):
|
|
45
|
+
"""LLM-related error."""
|
|
46
|
+
pass
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class LLMServiceError(LLMError):
|
|
50
|
+
"""Generic LLM service failure that is not a validation issue."""
|
|
51
|
+
pass
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class ToolError(DomainError):
|
|
55
|
+
"""Tool execution error."""
|
|
56
|
+
pass
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class ToolAuthorizationError(AuthorizationError):
|
|
60
|
+
"""Raised when user is not authorized to use a specific tool."""
|
|
61
|
+
pass
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class DataSourcePermissionError(AuthorizationError):
|
|
65
|
+
"""Raised when user lacks permission to access a data source."""
|
|
66
|
+
pass
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class LLMConfigurationError(ConfigurationError):
|
|
70
|
+
"""Raised when LLM configuration is invalid or incomplete."""
|
|
71
|
+
pass
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class SessionNotFoundError(SessionError):
|
|
75
|
+
"""Raised when a session cannot be found."""
|
|
76
|
+
pass
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class PromptOverrideError(DomainError):
|
|
80
|
+
"""Raised when MCP prompt override fails."""
|
|
81
|
+
pass
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class RateLimitError(LLMError):
|
|
85
|
+
"""Raised when LLM rate limit is exceeded."""
|
|
86
|
+
pass
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class LLMTimeoutError(LLMError):
|
|
90
|
+
"""Raised when LLM request times out."""
|
|
91
|
+
pass
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class LLMAuthenticationError(AuthenticationError):
|
|
95
|
+
"""Raised when LLM authentication fails."""
|
|
96
|
+
pass
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"""Domain models for messages."""
|
|
2
|
+
|
|
3
|
+
from .models import ConversationHistory, Message, MessageRole, MessageType, ToolCall, ToolResult
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
"Message",
|
|
7
|
+
"MessageRole",
|
|
8
|
+
"MessageType",
|
|
9
|
+
"ToolCall",
|
|
10
|
+
"ToolResult",
|
|
11
|
+
"ConversationHistory",
|
|
12
|
+
]
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"""Domain models for messages."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass, field
|
|
4
|
+
from datetime import datetime, timezone
|
|
5
|
+
from enum import Enum
|
|
6
|
+
from typing import Any, Dict, List, Literal, Optional
|
|
7
|
+
from uuid import UUID, uuid4
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class MessageRole(Enum):
|
|
11
|
+
"""Message role enumeration."""
|
|
12
|
+
USER = "user"
|
|
13
|
+
ASSISTANT = "assistant"
|
|
14
|
+
SYSTEM = "system"
|
|
15
|
+
TOOL = "tool"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class MessageType(Enum):
|
|
19
|
+
"""Message type enumeration."""
|
|
20
|
+
CHAT = "chat"
|
|
21
|
+
CHAT_RESPONSE = "chat_response"
|
|
22
|
+
ERROR = "error"
|
|
23
|
+
TOOL_CALL = "tool_call"
|
|
24
|
+
TOOL_RESULT = "tool_result"
|
|
25
|
+
AGENT_UPDATE = "agent_update"
|
|
26
|
+
INTERMEDIATE_UPDATE = "intermediate_update"
|
|
27
|
+
DOWNLOAD_FILE = "download_file"
|
|
28
|
+
FILE_DOWNLOAD = "file_download"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@dataclass
|
|
32
|
+
class Message:
|
|
33
|
+
"""Domain model for a chat message."""
|
|
34
|
+
id: UUID = field(default_factory=uuid4)
|
|
35
|
+
role: MessageRole = MessageRole.USER
|
|
36
|
+
content: str = ""
|
|
37
|
+
timestamp: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
|
|
38
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
39
|
+
|
|
40
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
41
|
+
"""Convert to dictionary for serialization."""
|
|
42
|
+
return {
|
|
43
|
+
"id": str(self.id),
|
|
44
|
+
"role": self.role.value,
|
|
45
|
+
"content": self.content,
|
|
46
|
+
"timestamp": self.timestamp.isoformat(),
|
|
47
|
+
"metadata": self.metadata
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
@classmethod
|
|
51
|
+
def from_dict(cls, data: Dict[str, Any]) -> "Message":
|
|
52
|
+
"""Create from dictionary."""
|
|
53
|
+
return cls(
|
|
54
|
+
id=UUID(data["id"]) if "id" in data else uuid4(),
|
|
55
|
+
role=MessageRole(data.get("role", "user")),
|
|
56
|
+
content=data.get("content", ""),
|
|
57
|
+
timestamp=datetime.fromisoformat(data["timestamp"]) if "timestamp" in data else datetime.now(timezone.utc),
|
|
58
|
+
metadata=data.get("metadata", {})
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@dataclass
|
|
63
|
+
class ToolCall:
|
|
64
|
+
"""Domain model for a tool call."""
|
|
65
|
+
id: str
|
|
66
|
+
name: str
|
|
67
|
+
arguments: Dict[str, Any]
|
|
68
|
+
|
|
69
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
70
|
+
"""Convert to dictionary."""
|
|
71
|
+
return {
|
|
72
|
+
"id": self.id,
|
|
73
|
+
"name": self.name,
|
|
74
|
+
"arguments": self.arguments
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
@dataclass
|
|
79
|
+
class ToolResult:
|
|
80
|
+
"""Domain model for a tool result with v2 MCP support."""
|
|
81
|
+
tool_call_id: str
|
|
82
|
+
content: str
|
|
83
|
+
success: bool = True
|
|
84
|
+
error: Optional[str] = None
|
|
85
|
+
artifacts: List[Dict[str, Any]] = field(default_factory=list)
|
|
86
|
+
display_config: Optional[Dict[str, Any]] = None
|
|
87
|
+
meta_data: Optional[Dict[str, Any]] = None
|
|
88
|
+
|
|
89
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
90
|
+
"""Convert to dictionary."""
|
|
91
|
+
result = {
|
|
92
|
+
"tool_call_id": self.tool_call_id,
|
|
93
|
+
"content": self.content,
|
|
94
|
+
"success": self.success,
|
|
95
|
+
"error": self.error,
|
|
96
|
+
"artifacts": self.artifacts,
|
|
97
|
+
}
|
|
98
|
+
if self.display_config:
|
|
99
|
+
result["display_config"] = self.display_config
|
|
100
|
+
if self.meta_data:
|
|
101
|
+
result["meta_data"] = self.meta_data
|
|
102
|
+
return result
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
@dataclass
|
|
106
|
+
class ConversationHistory:
|
|
107
|
+
"""Domain model for conversation history."""
|
|
108
|
+
messages: List[Message] = field(default_factory=list)
|
|
109
|
+
|
|
110
|
+
def add_message(self, message: Message) -> None:
|
|
111
|
+
"""Add a message to the history."""
|
|
112
|
+
self.messages.append(message)
|
|
113
|
+
|
|
114
|
+
def get_messages_for_llm(self) -> List[Dict[str, str]]:
|
|
115
|
+
"""Get messages formatted for LLM API."""
|
|
116
|
+
return [
|
|
117
|
+
{"role": msg.role.value, "content": msg.content}
|
|
118
|
+
for msg in self.messages
|
|
119
|
+
]
|
|
120
|
+
|
|
121
|
+
def to_dict(self) -> List[Dict[str, Any]]:
|
|
122
|
+
"""Convert to dictionary list."""
|
|
123
|
+
return [msg.to_dict() for msg in self.messages]
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
@dataclass
|
|
127
|
+
class ElicitationRequest:
|
|
128
|
+
"""Domain model for an elicitation request from MCP server."""
|
|
129
|
+
elicitation_id: str
|
|
130
|
+
tool_call_id: str
|
|
131
|
+
tool_name: str
|
|
132
|
+
message: str
|
|
133
|
+
response_schema: Dict[str, Any]
|
|
134
|
+
|
|
135
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
136
|
+
"""Convert to dictionary for WebSocket transmission."""
|
|
137
|
+
return {
|
|
138
|
+
"type": "elicitation_request",
|
|
139
|
+
"elicitation_id": self.elicitation_id,
|
|
140
|
+
"tool_call_id": self.tool_call_id,
|
|
141
|
+
"tool_name": self.tool_name,
|
|
142
|
+
"message": self.message,
|
|
143
|
+
"response_schema": self.response_schema
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
@dataclass
|
|
148
|
+
class ElicitationResponse:
|
|
149
|
+
"""Domain model for an elicitation response from user."""
|
|
150
|
+
elicitation_id: str
|
|
151
|
+
action: Literal["accept", "decline", "cancel"]
|
|
152
|
+
data: Optional[Dict[str, Any]] = None
|
|
153
|
+
|
|
154
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
155
|
+
"""Convert to dictionary."""
|
|
156
|
+
return {
|
|
157
|
+
"elicitation_id": self.elicitation_id,
|
|
158
|
+
"action": self.action,
|
|
159
|
+
"data": self.data
|
|
160
|
+
}
|