aiecs 1.0.1__py3-none-any.whl → 1.7.6__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.
Potentially problematic release.
This version of aiecs might be problematic. Click here for more details.
- aiecs/__init__.py +13 -16
- aiecs/__main__.py +7 -7
- aiecs/aiecs_client.py +269 -75
- aiecs/application/executors/operation_executor.py +79 -54
- aiecs/application/knowledge_graph/__init__.py +7 -0
- aiecs/application/knowledge_graph/builder/__init__.py +37 -0
- aiecs/application/knowledge_graph/builder/data_quality.py +302 -0
- aiecs/application/knowledge_graph/builder/data_reshaping.py +293 -0
- aiecs/application/knowledge_graph/builder/document_builder.py +369 -0
- aiecs/application/knowledge_graph/builder/graph_builder.py +490 -0
- aiecs/application/knowledge_graph/builder/import_optimizer.py +396 -0
- aiecs/application/knowledge_graph/builder/schema_inference.py +462 -0
- aiecs/application/knowledge_graph/builder/schema_mapping.py +563 -0
- aiecs/application/knowledge_graph/builder/structured_pipeline.py +1384 -0
- aiecs/application/knowledge_graph/builder/text_chunker.py +317 -0
- aiecs/application/knowledge_graph/extractors/__init__.py +27 -0
- aiecs/application/knowledge_graph/extractors/base.py +98 -0
- aiecs/application/knowledge_graph/extractors/llm_entity_extractor.py +422 -0
- aiecs/application/knowledge_graph/extractors/llm_relation_extractor.py +347 -0
- aiecs/application/knowledge_graph/extractors/ner_entity_extractor.py +241 -0
- aiecs/application/knowledge_graph/fusion/__init__.py +78 -0
- aiecs/application/knowledge_graph/fusion/ab_testing.py +395 -0
- aiecs/application/knowledge_graph/fusion/abbreviation_expander.py +327 -0
- aiecs/application/knowledge_graph/fusion/alias_index.py +597 -0
- aiecs/application/knowledge_graph/fusion/alias_matcher.py +384 -0
- aiecs/application/knowledge_graph/fusion/cache_coordinator.py +343 -0
- aiecs/application/knowledge_graph/fusion/entity_deduplicator.py +433 -0
- aiecs/application/knowledge_graph/fusion/entity_linker.py +511 -0
- aiecs/application/knowledge_graph/fusion/evaluation_dataset.py +240 -0
- aiecs/application/knowledge_graph/fusion/knowledge_fusion.py +632 -0
- aiecs/application/knowledge_graph/fusion/matching_config.py +489 -0
- aiecs/application/knowledge_graph/fusion/name_normalizer.py +352 -0
- aiecs/application/knowledge_graph/fusion/relation_deduplicator.py +183 -0
- aiecs/application/knowledge_graph/fusion/semantic_name_matcher.py +464 -0
- aiecs/application/knowledge_graph/fusion/similarity_pipeline.py +534 -0
- aiecs/application/knowledge_graph/pattern_matching/__init__.py +21 -0
- aiecs/application/knowledge_graph/pattern_matching/pattern_matcher.py +342 -0
- aiecs/application/knowledge_graph/pattern_matching/query_executor.py +366 -0
- aiecs/application/knowledge_graph/profiling/__init__.py +12 -0
- aiecs/application/knowledge_graph/profiling/query_plan_visualizer.py +195 -0
- aiecs/application/knowledge_graph/profiling/query_profiler.py +223 -0
- aiecs/application/knowledge_graph/reasoning/__init__.py +27 -0
- aiecs/application/knowledge_graph/reasoning/evidence_synthesis.py +341 -0
- aiecs/application/knowledge_graph/reasoning/inference_engine.py +500 -0
- aiecs/application/knowledge_graph/reasoning/logic_form_parser.py +163 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/__init__.py +79 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/ast_builder.py +513 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/ast_nodes.py +913 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/ast_validator.py +866 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/error_handler.py +475 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/parser.py +396 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/query_context.py +208 -0
- aiecs/application/knowledge_graph/reasoning/logic_query_integration.py +170 -0
- aiecs/application/knowledge_graph/reasoning/query_planner.py +855 -0
- aiecs/application/knowledge_graph/reasoning/reasoning_engine.py +518 -0
- aiecs/application/knowledge_graph/retrieval/__init__.py +27 -0
- aiecs/application/knowledge_graph/retrieval/query_intent_classifier.py +211 -0
- aiecs/application/knowledge_graph/retrieval/retrieval_strategies.py +592 -0
- aiecs/application/knowledge_graph/retrieval/strategy_types.py +23 -0
- aiecs/application/knowledge_graph/search/__init__.py +59 -0
- aiecs/application/knowledge_graph/search/hybrid_search.py +457 -0
- aiecs/application/knowledge_graph/search/reranker.py +293 -0
- aiecs/application/knowledge_graph/search/reranker_strategies.py +535 -0
- aiecs/application/knowledge_graph/search/text_similarity.py +392 -0
- aiecs/application/knowledge_graph/traversal/__init__.py +15 -0
- aiecs/application/knowledge_graph/traversal/enhanced_traversal.py +305 -0
- aiecs/application/knowledge_graph/traversal/path_scorer.py +271 -0
- aiecs/application/knowledge_graph/validators/__init__.py +13 -0
- aiecs/application/knowledge_graph/validators/relation_validator.py +239 -0
- aiecs/application/knowledge_graph/visualization/__init__.py +11 -0
- aiecs/application/knowledge_graph/visualization/graph_visualizer.py +313 -0
- aiecs/common/__init__.py +9 -0
- aiecs/common/knowledge_graph/__init__.py +17 -0
- aiecs/common/knowledge_graph/runnable.py +471 -0
- aiecs/config/__init__.py +20 -5
- aiecs/config/config.py +762 -31
- aiecs/config/graph_config.py +131 -0
- aiecs/config/tool_config.py +399 -0
- aiecs/core/__init__.py +29 -13
- aiecs/core/interface/__init__.py +2 -2
- aiecs/core/interface/execution_interface.py +22 -22
- aiecs/core/interface/storage_interface.py +37 -88
- aiecs/core/registry/__init__.py +31 -0
- aiecs/core/registry/service_registry.py +92 -0
- aiecs/domain/__init__.py +270 -1
- aiecs/domain/agent/__init__.py +191 -0
- aiecs/domain/agent/base_agent.py +3870 -0
- aiecs/domain/agent/exceptions.py +99 -0
- aiecs/domain/agent/graph_aware_mixin.py +569 -0
- aiecs/domain/agent/hybrid_agent.py +1435 -0
- aiecs/domain/agent/integration/__init__.py +29 -0
- aiecs/domain/agent/integration/context_compressor.py +216 -0
- aiecs/domain/agent/integration/context_engine_adapter.py +587 -0
- aiecs/domain/agent/integration/protocols.py +281 -0
- aiecs/domain/agent/integration/retry_policy.py +218 -0
- aiecs/domain/agent/integration/role_config.py +213 -0
- aiecs/domain/agent/knowledge_aware_agent.py +1892 -0
- aiecs/domain/agent/lifecycle.py +291 -0
- aiecs/domain/agent/llm_agent.py +692 -0
- aiecs/domain/agent/memory/__init__.py +12 -0
- aiecs/domain/agent/memory/conversation.py +1124 -0
- aiecs/domain/agent/migration/__init__.py +14 -0
- aiecs/domain/agent/migration/conversion.py +163 -0
- aiecs/domain/agent/migration/legacy_wrapper.py +86 -0
- aiecs/domain/agent/models.py +884 -0
- aiecs/domain/agent/observability.py +479 -0
- aiecs/domain/agent/persistence.py +449 -0
- aiecs/domain/agent/prompts/__init__.py +29 -0
- aiecs/domain/agent/prompts/builder.py +159 -0
- aiecs/domain/agent/prompts/formatters.py +187 -0
- aiecs/domain/agent/prompts/template.py +255 -0
- aiecs/domain/agent/registry.py +253 -0
- aiecs/domain/agent/tool_agent.py +444 -0
- aiecs/domain/agent/tools/__init__.py +15 -0
- aiecs/domain/agent/tools/schema_generator.py +364 -0
- aiecs/domain/community/__init__.py +155 -0
- aiecs/domain/community/agent_adapter.py +469 -0
- aiecs/domain/community/analytics.py +432 -0
- aiecs/domain/community/collaborative_workflow.py +648 -0
- aiecs/domain/community/communication_hub.py +634 -0
- aiecs/domain/community/community_builder.py +320 -0
- aiecs/domain/community/community_integration.py +796 -0
- aiecs/domain/community/community_manager.py +803 -0
- aiecs/domain/community/decision_engine.py +849 -0
- aiecs/domain/community/exceptions.py +231 -0
- aiecs/domain/community/models/__init__.py +33 -0
- aiecs/domain/community/models/community_models.py +234 -0
- aiecs/domain/community/resource_manager.py +461 -0
- aiecs/domain/community/shared_context_manager.py +589 -0
- aiecs/domain/context/__init__.py +40 -10
- aiecs/domain/context/context_engine.py +1910 -0
- aiecs/domain/context/conversation_models.py +87 -53
- aiecs/domain/context/graph_memory.py +582 -0
- aiecs/domain/execution/model.py +12 -4
- aiecs/domain/knowledge_graph/__init__.py +19 -0
- aiecs/domain/knowledge_graph/models/__init__.py +52 -0
- aiecs/domain/knowledge_graph/models/entity.py +148 -0
- aiecs/domain/knowledge_graph/models/evidence.py +178 -0
- aiecs/domain/knowledge_graph/models/inference_rule.py +184 -0
- aiecs/domain/knowledge_graph/models/path.py +171 -0
- aiecs/domain/knowledge_graph/models/path_pattern.py +171 -0
- aiecs/domain/knowledge_graph/models/query.py +261 -0
- aiecs/domain/knowledge_graph/models/query_plan.py +181 -0
- aiecs/domain/knowledge_graph/models/relation.py +202 -0
- aiecs/domain/knowledge_graph/schema/__init__.py +23 -0
- aiecs/domain/knowledge_graph/schema/entity_type.py +131 -0
- aiecs/domain/knowledge_graph/schema/graph_schema.py +253 -0
- aiecs/domain/knowledge_graph/schema/property_schema.py +143 -0
- aiecs/domain/knowledge_graph/schema/relation_type.py +163 -0
- aiecs/domain/knowledge_graph/schema/schema_manager.py +691 -0
- aiecs/domain/knowledge_graph/schema/type_enums.py +209 -0
- aiecs/domain/task/dsl_processor.py +172 -56
- aiecs/domain/task/model.py +20 -8
- aiecs/domain/task/task_context.py +27 -24
- aiecs/infrastructure/__init__.py +0 -2
- aiecs/infrastructure/graph_storage/__init__.py +11 -0
- aiecs/infrastructure/graph_storage/base.py +837 -0
- aiecs/infrastructure/graph_storage/batch_operations.py +458 -0
- aiecs/infrastructure/graph_storage/cache.py +424 -0
- aiecs/infrastructure/graph_storage/distributed.py +223 -0
- aiecs/infrastructure/graph_storage/error_handling.py +380 -0
- aiecs/infrastructure/graph_storage/graceful_degradation.py +294 -0
- aiecs/infrastructure/graph_storage/health_checks.py +378 -0
- aiecs/infrastructure/graph_storage/in_memory.py +1197 -0
- aiecs/infrastructure/graph_storage/index_optimization.py +446 -0
- aiecs/infrastructure/graph_storage/lazy_loading.py +431 -0
- aiecs/infrastructure/graph_storage/metrics.py +344 -0
- aiecs/infrastructure/graph_storage/migration.py +400 -0
- aiecs/infrastructure/graph_storage/pagination.py +483 -0
- aiecs/infrastructure/graph_storage/performance_monitoring.py +456 -0
- aiecs/infrastructure/graph_storage/postgres.py +1563 -0
- aiecs/infrastructure/graph_storage/property_storage.py +353 -0
- aiecs/infrastructure/graph_storage/protocols.py +76 -0
- aiecs/infrastructure/graph_storage/query_optimizer.py +642 -0
- aiecs/infrastructure/graph_storage/schema_cache.py +290 -0
- aiecs/infrastructure/graph_storage/sqlite.py +1373 -0
- aiecs/infrastructure/graph_storage/streaming.py +487 -0
- aiecs/infrastructure/graph_storage/tenant.py +412 -0
- aiecs/infrastructure/messaging/celery_task_manager.py +92 -54
- aiecs/infrastructure/messaging/websocket_manager.py +51 -35
- aiecs/infrastructure/monitoring/__init__.py +22 -0
- aiecs/infrastructure/monitoring/executor_metrics.py +45 -11
- aiecs/infrastructure/monitoring/global_metrics_manager.py +212 -0
- aiecs/infrastructure/monitoring/structured_logger.py +3 -7
- aiecs/infrastructure/monitoring/tracing_manager.py +63 -35
- aiecs/infrastructure/persistence/__init__.py +14 -1
- aiecs/infrastructure/persistence/context_engine_client.py +184 -0
- aiecs/infrastructure/persistence/database_manager.py +67 -43
- aiecs/infrastructure/persistence/file_storage.py +180 -103
- aiecs/infrastructure/persistence/redis_client.py +74 -21
- aiecs/llm/__init__.py +73 -25
- aiecs/llm/callbacks/__init__.py +11 -0
- aiecs/llm/{custom_callbacks.py → callbacks/custom_callbacks.py} +26 -19
- aiecs/llm/client_factory.py +224 -36
- aiecs/llm/client_resolver.py +155 -0
- aiecs/llm/clients/__init__.py +38 -0
- aiecs/llm/clients/base_client.py +324 -0
- aiecs/llm/clients/google_function_calling_mixin.py +457 -0
- aiecs/llm/clients/googleai_client.py +241 -0
- aiecs/llm/clients/openai_client.py +158 -0
- aiecs/llm/clients/openai_compatible_mixin.py +367 -0
- aiecs/llm/clients/vertex_client.py +897 -0
- aiecs/llm/clients/xai_client.py +201 -0
- aiecs/llm/config/__init__.py +51 -0
- aiecs/llm/config/config_loader.py +272 -0
- aiecs/llm/config/config_validator.py +206 -0
- aiecs/llm/config/model_config.py +143 -0
- aiecs/llm/protocols.py +149 -0
- aiecs/llm/utils/__init__.py +10 -0
- aiecs/llm/utils/validate_config.py +89 -0
- aiecs/main.py +140 -121
- aiecs/scripts/aid/VERSION_MANAGEMENT.md +138 -0
- aiecs/scripts/aid/__init__.py +19 -0
- aiecs/scripts/aid/module_checker.py +499 -0
- aiecs/scripts/aid/version_manager.py +235 -0
- aiecs/scripts/{DEPENDENCY_SYSTEM_SUMMARY.md → dependance_check/DEPENDENCY_SYSTEM_SUMMARY.md} +1 -0
- aiecs/scripts/{README_DEPENDENCY_CHECKER.md → dependance_check/README_DEPENDENCY_CHECKER.md} +1 -0
- aiecs/scripts/dependance_check/__init__.py +15 -0
- aiecs/scripts/dependance_check/dependency_checker.py +1835 -0
- aiecs/scripts/{dependency_fixer.py → dependance_check/dependency_fixer.py} +192 -90
- aiecs/scripts/{download_nlp_data.py → dependance_check/download_nlp_data.py} +203 -71
- aiecs/scripts/dependance_patch/__init__.py +7 -0
- aiecs/scripts/dependance_patch/fix_weasel/__init__.py +11 -0
- aiecs/scripts/{fix_weasel_validator.py → dependance_patch/fix_weasel/fix_weasel_validator.py} +21 -14
- aiecs/scripts/{patch_weasel_library.sh → dependance_patch/fix_weasel/patch_weasel_library.sh} +1 -1
- aiecs/scripts/knowledge_graph/__init__.py +3 -0
- aiecs/scripts/knowledge_graph/run_threshold_experiments.py +212 -0
- aiecs/scripts/migrations/multi_tenancy/README.md +142 -0
- aiecs/scripts/tools_develop/README.md +671 -0
- aiecs/scripts/tools_develop/README_CONFIG_CHECKER.md +273 -0
- aiecs/scripts/tools_develop/TOOLS_CONFIG_GUIDE.md +1287 -0
- aiecs/scripts/tools_develop/TOOL_AUTO_DISCOVERY.md +234 -0
- aiecs/scripts/tools_develop/__init__.py +21 -0
- aiecs/scripts/tools_develop/check_all_tools_config.py +548 -0
- aiecs/scripts/tools_develop/check_type_annotations.py +257 -0
- aiecs/scripts/tools_develop/pre-commit-schema-coverage.sh +66 -0
- aiecs/scripts/tools_develop/schema_coverage.py +511 -0
- aiecs/scripts/tools_develop/validate_tool_schemas.py +475 -0
- aiecs/scripts/tools_develop/verify_executor_config_fix.py +98 -0
- aiecs/scripts/tools_develop/verify_tools.py +352 -0
- aiecs/tasks/__init__.py +0 -1
- aiecs/tasks/worker.py +115 -47
- aiecs/tools/__init__.py +194 -72
- aiecs/tools/apisource/__init__.py +99 -0
- aiecs/tools/apisource/intelligence/__init__.py +19 -0
- aiecs/tools/apisource/intelligence/data_fusion.py +632 -0
- aiecs/tools/apisource/intelligence/query_analyzer.py +417 -0
- aiecs/tools/apisource/intelligence/search_enhancer.py +385 -0
- aiecs/tools/apisource/monitoring/__init__.py +9 -0
- aiecs/tools/apisource/monitoring/metrics.py +330 -0
- aiecs/tools/apisource/providers/__init__.py +112 -0
- aiecs/tools/apisource/providers/base.py +671 -0
- aiecs/tools/apisource/providers/census.py +397 -0
- aiecs/tools/apisource/providers/fred.py +535 -0
- aiecs/tools/apisource/providers/newsapi.py +409 -0
- aiecs/tools/apisource/providers/worldbank.py +352 -0
- aiecs/tools/apisource/reliability/__init__.py +12 -0
- aiecs/tools/apisource/reliability/error_handler.py +363 -0
- aiecs/tools/apisource/reliability/fallback_strategy.py +376 -0
- aiecs/tools/apisource/tool.py +832 -0
- aiecs/tools/apisource/utils/__init__.py +9 -0
- aiecs/tools/apisource/utils/validators.py +334 -0
- aiecs/tools/base_tool.py +415 -21
- aiecs/tools/docs/__init__.py +121 -0
- aiecs/tools/docs/ai_document_orchestrator.py +607 -0
- aiecs/tools/docs/ai_document_writer_orchestrator.py +2350 -0
- aiecs/tools/docs/content_insertion_tool.py +1320 -0
- aiecs/tools/docs/document_creator_tool.py +1323 -0
- aiecs/tools/docs/document_layout_tool.py +1160 -0
- aiecs/tools/docs/document_parser_tool.py +1011 -0
- aiecs/tools/docs/document_writer_tool.py +1829 -0
- aiecs/tools/knowledge_graph/__init__.py +17 -0
- aiecs/tools/knowledge_graph/graph_reasoning_tool.py +807 -0
- aiecs/tools/knowledge_graph/graph_search_tool.py +944 -0
- aiecs/tools/knowledge_graph/kg_builder_tool.py +524 -0
- aiecs/tools/langchain_adapter.py +300 -138
- aiecs/tools/schema_generator.py +455 -0
- aiecs/tools/search_tool/__init__.py +100 -0
- aiecs/tools/search_tool/analyzers.py +581 -0
- aiecs/tools/search_tool/cache.py +264 -0
- aiecs/tools/search_tool/constants.py +128 -0
- aiecs/tools/search_tool/context.py +224 -0
- aiecs/tools/search_tool/core.py +778 -0
- aiecs/tools/search_tool/deduplicator.py +119 -0
- aiecs/tools/search_tool/error_handler.py +242 -0
- aiecs/tools/search_tool/metrics.py +343 -0
- aiecs/tools/search_tool/rate_limiter.py +172 -0
- aiecs/tools/search_tool/schemas.py +275 -0
- aiecs/tools/statistics/__init__.py +80 -0
- aiecs/tools/statistics/ai_data_analysis_orchestrator.py +646 -0
- aiecs/tools/statistics/ai_insight_generator_tool.py +508 -0
- aiecs/tools/statistics/ai_report_orchestrator_tool.py +684 -0
- aiecs/tools/statistics/data_loader_tool.py +555 -0
- aiecs/tools/statistics/data_profiler_tool.py +638 -0
- aiecs/tools/statistics/data_transformer_tool.py +580 -0
- aiecs/tools/statistics/data_visualizer_tool.py +498 -0
- aiecs/tools/statistics/model_trainer_tool.py +507 -0
- aiecs/tools/statistics/statistical_analyzer_tool.py +472 -0
- aiecs/tools/task_tools/__init__.py +49 -36
- aiecs/tools/task_tools/chart_tool.py +200 -184
- aiecs/tools/task_tools/classfire_tool.py +268 -267
- aiecs/tools/task_tools/image_tool.py +175 -131
- aiecs/tools/task_tools/office_tool.py +226 -146
- aiecs/tools/task_tools/pandas_tool.py +477 -121
- aiecs/tools/task_tools/report_tool.py +390 -142
- aiecs/tools/task_tools/research_tool.py +149 -79
- aiecs/tools/task_tools/scraper_tool.py +339 -145
- aiecs/tools/task_tools/stats_tool.py +448 -209
- aiecs/tools/temp_file_manager.py +26 -24
- aiecs/tools/tool_executor/__init__.py +18 -16
- aiecs/tools/tool_executor/tool_executor.py +364 -52
- aiecs/utils/LLM_output_structor.py +74 -48
- aiecs/utils/__init__.py +14 -3
- aiecs/utils/base_callback.py +0 -3
- aiecs/utils/cache_provider.py +696 -0
- aiecs/utils/execution_utils.py +50 -31
- aiecs/utils/prompt_loader.py +1 -0
- aiecs/utils/token_usage_repository.py +37 -11
- aiecs/ws/socket_server.py +14 -4
- {aiecs-1.0.1.dist-info → aiecs-1.7.6.dist-info}/METADATA +52 -15
- aiecs-1.7.6.dist-info/RECORD +337 -0
- aiecs-1.7.6.dist-info/entry_points.txt +13 -0
- aiecs/config/registry.py +0 -19
- aiecs/domain/context/content_engine.py +0 -982
- aiecs/llm/base_client.py +0 -99
- aiecs/llm/openai_client.py +0 -125
- aiecs/llm/vertex_client.py +0 -186
- aiecs/llm/xai_client.py +0 -184
- aiecs/scripts/dependency_checker.py +0 -857
- aiecs/scripts/quick_dependency_check.py +0 -269
- aiecs/tools/task_tools/search_api.py +0 -7
- aiecs-1.0.1.dist-info/RECORD +0 -90
- aiecs-1.0.1.dist-info/entry_points.txt +0 -7
- /aiecs/scripts/{setup_nlp_data.sh → dependance_check/setup_nlp_data.sh} +0 -0
- /aiecs/scripts/{README_WEASEL_PATCH.md → dependance_patch/fix_weasel/README_WEASEL_PATCH.md} +0 -0
- /aiecs/scripts/{fix_weasel_validator.sh → dependance_patch/fix_weasel/fix_weasel_validator.sh} +0 -0
- /aiecs/scripts/{run_weasel_patch.sh → dependance_patch/fix_weasel/run_weasel_patch.sh} +0 -0
- {aiecs-1.0.1.dist-info → aiecs-1.7.6.dist-info}/WHEEL +0 -0
- {aiecs-1.0.1.dist-info → aiecs-1.7.6.dist-info}/licenses/LICENSE +0 -0
- {aiecs-1.0.1.dist-info → aiecs-1.7.6.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,587 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ContextEngine Adapter
|
|
3
|
+
|
|
4
|
+
Adapter for integrating agent persistence with AIECS ContextEngine.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
import uuid
|
|
9
|
+
from typing import Dict, Any, Optional, List, TYPE_CHECKING
|
|
10
|
+
from datetime import datetime
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from aiecs.domain.context.context_engine import ContextEngine
|
|
14
|
+
|
|
15
|
+
from aiecs.domain.agent.base_agent import BaseAIAgent
|
|
16
|
+
|
|
17
|
+
logger = logging.getLogger(__name__)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class ContextEngineAdapter:
|
|
21
|
+
"""
|
|
22
|
+
Adapter for persisting agent state to ContextEngine.
|
|
23
|
+
|
|
24
|
+
Uses ContextEngine's checkpoint system for versioned state storage
|
|
25
|
+
and TaskContext for session-based state management.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(self, context_engine: "ContextEngine", user_id: str = "system"):
|
|
29
|
+
"""
|
|
30
|
+
Initialize adapter.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
context_engine: ContextEngine instance
|
|
34
|
+
user_id: User identifier for session management
|
|
35
|
+
"""
|
|
36
|
+
if context_engine is None:
|
|
37
|
+
raise ValueError("ContextEngine instance is required")
|
|
38
|
+
|
|
39
|
+
self.context_engine = context_engine
|
|
40
|
+
self.user_id = user_id
|
|
41
|
+
self._agent_state_prefix = "agent_state"
|
|
42
|
+
self._agent_conversation_prefix = "agent_conversation"
|
|
43
|
+
logger.info("ContextEngineAdapter initialized")
|
|
44
|
+
|
|
45
|
+
async def save_agent_state(
|
|
46
|
+
self,
|
|
47
|
+
agent_id: str,
|
|
48
|
+
state: Dict[str, Any],
|
|
49
|
+
version: Optional[str] = None,
|
|
50
|
+
) -> str:
|
|
51
|
+
"""
|
|
52
|
+
Save agent state to ContextEngine using checkpoint system.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
agent_id: Agent identifier
|
|
56
|
+
state: Agent state dictionary
|
|
57
|
+
version: Optional version identifier (auto-generated if None)
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
Version identifier
|
|
61
|
+
"""
|
|
62
|
+
if version is None:
|
|
63
|
+
version = str(uuid.uuid4())
|
|
64
|
+
|
|
65
|
+
checkpoint_data = {
|
|
66
|
+
"agent_id": agent_id,
|
|
67
|
+
"state": state,
|
|
68
|
+
"timestamp": datetime.utcnow().isoformat(),
|
|
69
|
+
"version": version,
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
# Store as checkpoint (thread_id = agent_id)
|
|
73
|
+
await self.context_engine.store_checkpoint(
|
|
74
|
+
thread_id=agent_id,
|
|
75
|
+
checkpoint_id=version,
|
|
76
|
+
checkpoint_data=checkpoint_data,
|
|
77
|
+
metadata={"type": "agent_state", "agent_id": agent_id},
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
logger.debug(f"Saved agent {agent_id} state version {version} to ContextEngine")
|
|
81
|
+
return version
|
|
82
|
+
|
|
83
|
+
async def load_agent_state(self, agent_id: str, version: Optional[str] = None) -> Optional[Dict[str, Any]]:
|
|
84
|
+
"""
|
|
85
|
+
Load agent state from ContextEngine.
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
agent_id: Agent identifier
|
|
89
|
+
version: Optional version identifier (loads latest if None)
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
Agent state dictionary or None
|
|
93
|
+
"""
|
|
94
|
+
if version is None:
|
|
95
|
+
return None
|
|
96
|
+
checkpoint = await self.context_engine.get_checkpoint(thread_id=agent_id, checkpoint_id=version)
|
|
97
|
+
|
|
98
|
+
if checkpoint and "data" in checkpoint:
|
|
99
|
+
checkpoint_data = checkpoint["data"]
|
|
100
|
+
if isinstance(checkpoint_data, dict) and "state" in checkpoint_data:
|
|
101
|
+
logger.debug(f"Loaded agent {agent_id} state version {version or 'latest'}")
|
|
102
|
+
return checkpoint_data["state"]
|
|
103
|
+
|
|
104
|
+
logger.debug(f"No state found for agent {agent_id} version {version or 'latest'}")
|
|
105
|
+
return None
|
|
106
|
+
|
|
107
|
+
async def list_agent_versions(self, agent_id: str) -> List[Dict[str, Any]]:
|
|
108
|
+
"""
|
|
109
|
+
List all versions of an agent's state.
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
agent_id: Agent identifier
|
|
113
|
+
|
|
114
|
+
Returns:
|
|
115
|
+
List of version metadata dictionaries
|
|
116
|
+
"""
|
|
117
|
+
checkpoints = await self.context_engine.list_checkpoints(thread_id=agent_id)
|
|
118
|
+
if not checkpoints:
|
|
119
|
+
return []
|
|
120
|
+
|
|
121
|
+
versions = []
|
|
122
|
+
for checkpoint in checkpoints:
|
|
123
|
+
# list_checkpoints returns dicts with "data" key containing
|
|
124
|
+
# checkpoint_data
|
|
125
|
+
if isinstance(checkpoint, dict):
|
|
126
|
+
data = checkpoint.get("data", {})
|
|
127
|
+
if isinstance(data, dict) and "version" in data:
|
|
128
|
+
versions.append(
|
|
129
|
+
{
|
|
130
|
+
"version": data["version"],
|
|
131
|
+
"timestamp": data.get("timestamp"),
|
|
132
|
+
"metadata": checkpoint.get("metadata", {}),
|
|
133
|
+
}
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
# Sort by timestamp descending
|
|
137
|
+
versions.sort(key=lambda v: v.get("timestamp", ""), reverse=True)
|
|
138
|
+
return versions
|
|
139
|
+
|
|
140
|
+
async def save_conversation_history(self, session_id: str, messages: List[Dict[str, Any]]) -> None:
|
|
141
|
+
"""
|
|
142
|
+
Save conversation history to ContextEngine.
|
|
143
|
+
|
|
144
|
+
Args:
|
|
145
|
+
session_id: Session identifier
|
|
146
|
+
messages: List of message dictionaries with 'role' and 'content'
|
|
147
|
+
"""
|
|
148
|
+
# Ensure session exists
|
|
149
|
+
session = await self.context_engine.get_session(session_id)
|
|
150
|
+
if not session:
|
|
151
|
+
await self.context_engine.create_session(
|
|
152
|
+
session_id=session_id,
|
|
153
|
+
user_id=self.user_id,
|
|
154
|
+
metadata={"type": "agent_conversation"},
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
# Store messages using ContextEngine's conversation API
|
|
158
|
+
for msg in messages:
|
|
159
|
+
role = msg.get("role", "user")
|
|
160
|
+
content = msg.get("content", "")
|
|
161
|
+
metadata = msg.get("metadata", {})
|
|
162
|
+
|
|
163
|
+
await self.context_engine.add_conversation_message(
|
|
164
|
+
session_id=session_id,
|
|
165
|
+
role=role,
|
|
166
|
+
content=content,
|
|
167
|
+
metadata=metadata,
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
logger.debug(f"Saved {len(messages)} messages to session {session_id}")
|
|
171
|
+
|
|
172
|
+
async def load_conversation_history(self, session_id: str, limit: int = 50) -> List[Dict[str, Any]]:
|
|
173
|
+
"""
|
|
174
|
+
Load conversation history from ContextEngine.
|
|
175
|
+
|
|
176
|
+
Args:
|
|
177
|
+
session_id: Session identifier
|
|
178
|
+
limit: Maximum number of messages to retrieve
|
|
179
|
+
|
|
180
|
+
Returns:
|
|
181
|
+
List of message dictionaries
|
|
182
|
+
"""
|
|
183
|
+
messages = await self.context_engine.get_conversation_history(session_id=session_id, limit=limit)
|
|
184
|
+
|
|
185
|
+
# Convert ConversationMessage objects to dictionaries
|
|
186
|
+
# messages is List[Dict[str, Any]] from get_conversation_history
|
|
187
|
+
result = []
|
|
188
|
+
for msg in messages:
|
|
189
|
+
if isinstance(msg, dict):
|
|
190
|
+
result.append(msg)
|
|
191
|
+
else:
|
|
192
|
+
result.append(
|
|
193
|
+
{
|
|
194
|
+
"role": getattr(msg, "role", ""),
|
|
195
|
+
"content": getattr(msg, "content", ""),
|
|
196
|
+
"timestamp": (getattr(msg, "timestamp", "").isoformat() if hasattr(getattr(msg, "timestamp", None), "isoformat") else str(getattr(msg, "timestamp", ""))),
|
|
197
|
+
"metadata": getattr(msg, "metadata", {}),
|
|
198
|
+
}
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
logger.debug(f"Loaded {len(result)} messages from session {session_id}")
|
|
202
|
+
return result
|
|
203
|
+
|
|
204
|
+
async def delete_agent_state(self, agent_id: str, version: Optional[str] = None) -> None:
|
|
205
|
+
"""
|
|
206
|
+
Delete agent state from ContextEngine.
|
|
207
|
+
|
|
208
|
+
Args:
|
|
209
|
+
agent_id: Agent identifier
|
|
210
|
+
version: Optional version identifier (deletes all if None)
|
|
211
|
+
"""
|
|
212
|
+
# Note: ContextEngine doesn't have explicit delete for checkpoints
|
|
213
|
+
# We'll store a tombstone checkpoint or rely on TTL
|
|
214
|
+
if version:
|
|
215
|
+
# Store empty state as deletion marker
|
|
216
|
+
await self.context_engine.store_checkpoint(
|
|
217
|
+
thread_id=agent_id,
|
|
218
|
+
checkpoint_id=f"{version}_deleted",
|
|
219
|
+
checkpoint_data={"deleted": True, "original_version": version},
|
|
220
|
+
metadata={"type": "deletion_marker"},
|
|
221
|
+
)
|
|
222
|
+
logger.debug(f"Marked agent {agent_id} state version {version or 'all'} for deletion")
|
|
223
|
+
|
|
224
|
+
# AgentPersistence Protocol implementation
|
|
225
|
+
async def save(self, agent: BaseAIAgent) -> None:
|
|
226
|
+
"""Save agent state (implements AgentPersistence protocol)."""
|
|
227
|
+
state = agent.to_dict()
|
|
228
|
+
await self.save_agent_state(agent.agent_id, state)
|
|
229
|
+
|
|
230
|
+
async def load(self, agent_id: str) -> Dict[str, Any]:
|
|
231
|
+
"""Load agent state (implements AgentPersistence protocol)."""
|
|
232
|
+
state = await self.load_agent_state(agent_id)
|
|
233
|
+
if state is None:
|
|
234
|
+
raise KeyError(f"Agent {agent_id} not found in storage")
|
|
235
|
+
return state
|
|
236
|
+
|
|
237
|
+
async def exists(self, agent_id: str) -> bool:
|
|
238
|
+
"""Check if agent state exists (implements AgentPersistence protocol)."""
|
|
239
|
+
state = await self.load_agent_state(agent_id)
|
|
240
|
+
return state is not None
|
|
241
|
+
|
|
242
|
+
async def delete(self, agent_id: str) -> None:
|
|
243
|
+
"""Delete agent state (implements AgentPersistence protocol)."""
|
|
244
|
+
await self.delete_agent_state(agent_id)
|
|
245
|
+
|
|
246
|
+
# ==================== Session Management Methods ====================
|
|
247
|
+
|
|
248
|
+
def create_session(
|
|
249
|
+
self,
|
|
250
|
+
session_id: Optional[str] = None,
|
|
251
|
+
user_id: Optional[str] = None,
|
|
252
|
+
metadata: Optional[Dict] = None,
|
|
253
|
+
) -> str:
|
|
254
|
+
"""
|
|
255
|
+
Create a new session (sync version - not recommended with ContextEngine).
|
|
256
|
+
|
|
257
|
+
This is a synchronous wrapper that raises NotImplementedError.
|
|
258
|
+
Use acreate_session() instead for ContextEngine integration.
|
|
259
|
+
|
|
260
|
+
Args:
|
|
261
|
+
session_id: Optional custom session ID
|
|
262
|
+
user_id: Optional user ID
|
|
263
|
+
metadata: Optional session metadata
|
|
264
|
+
|
|
265
|
+
Raises:
|
|
266
|
+
NotImplementedError: Sync version not supported with ContextEngine
|
|
267
|
+
|
|
268
|
+
Note:
|
|
269
|
+
ContextEngine operations are async. Use acreate_session() instead.
|
|
270
|
+
"""
|
|
271
|
+
raise NotImplementedError("Synchronous create_session not supported with ContextEngine. " "Use acreate_session() instead.")
|
|
272
|
+
|
|
273
|
+
async def acreate_session(
|
|
274
|
+
self,
|
|
275
|
+
session_id: Optional[str] = None,
|
|
276
|
+
user_id: Optional[str] = None,
|
|
277
|
+
metadata: Optional[Dict] = None,
|
|
278
|
+
) -> str:
|
|
279
|
+
"""
|
|
280
|
+
Create a new session (async version with ContextEngine integration).
|
|
281
|
+
|
|
282
|
+
Args:
|
|
283
|
+
session_id: Optional custom session ID (auto-generated if None)
|
|
284
|
+
user_id: Optional user ID (defaults to adapter's user_id)
|
|
285
|
+
metadata: Optional session metadata
|
|
286
|
+
|
|
287
|
+
Returns:
|
|
288
|
+
Session ID
|
|
289
|
+
|
|
290
|
+
Example:
|
|
291
|
+
adapter = ContextEngineAdapter(context_engine)
|
|
292
|
+
session_id = await adapter.acreate_session(
|
|
293
|
+
user_id="user-123",
|
|
294
|
+
metadata={"source": "web", "language": "en"}
|
|
295
|
+
)
|
|
296
|
+
"""
|
|
297
|
+
if session_id is None:
|
|
298
|
+
session_id = f"session_{uuid.uuid4()}"
|
|
299
|
+
|
|
300
|
+
user_id = user_id or self.user_id
|
|
301
|
+
metadata = metadata or {}
|
|
302
|
+
|
|
303
|
+
await self.context_engine.create_session(session_id=session_id, user_id=user_id, metadata=metadata)
|
|
304
|
+
|
|
305
|
+
logger.debug(f"Created session {session_id} via ContextEngine")
|
|
306
|
+
return session_id
|
|
307
|
+
|
|
308
|
+
def get_session(self, session_id: str) -> Optional[Dict[str, Any]]:
|
|
309
|
+
"""
|
|
310
|
+
Get session (sync version - not recommended with ContextEngine).
|
|
311
|
+
|
|
312
|
+
This is a synchronous wrapper that raises NotImplementedError.
|
|
313
|
+
Use aget_session() instead for ContextEngine integration.
|
|
314
|
+
|
|
315
|
+
Args:
|
|
316
|
+
session_id: Session ID
|
|
317
|
+
|
|
318
|
+
Raises:
|
|
319
|
+
NotImplementedError: Sync version not supported with ContextEngine
|
|
320
|
+
|
|
321
|
+
Note:
|
|
322
|
+
ContextEngine operations are async. Use aget_session() instead.
|
|
323
|
+
"""
|
|
324
|
+
raise NotImplementedError("Synchronous get_session not supported with ContextEngine. " "Use aget_session() instead.")
|
|
325
|
+
|
|
326
|
+
async def aget_session(self, session_id: str) -> Optional[Dict[str, Any]]:
|
|
327
|
+
"""
|
|
328
|
+
Get session (async version with ContextEngine integration).
|
|
329
|
+
|
|
330
|
+
Args:
|
|
331
|
+
session_id: Session ID
|
|
332
|
+
|
|
333
|
+
Returns:
|
|
334
|
+
Session data dictionary or None if not found
|
|
335
|
+
|
|
336
|
+
Example:
|
|
337
|
+
session = await adapter.aget_session(session_id)
|
|
338
|
+
if session:
|
|
339
|
+
print(f"Session status: {session.status}")
|
|
340
|
+
print(f"Request count: {session.request_count}")
|
|
341
|
+
"""
|
|
342
|
+
session = await self.context_engine.get_session(session_id)
|
|
343
|
+
|
|
344
|
+
if session:
|
|
345
|
+
logger.debug(f"Retrieved session {session_id} from ContextEngine")
|
|
346
|
+
# session is already a dict from get_session()
|
|
347
|
+
if isinstance(session, dict):
|
|
348
|
+
return session
|
|
349
|
+
# Convert SessionMetrics to dict if it's a dataclass
|
|
350
|
+
elif hasattr(session, "to_dict"):
|
|
351
|
+
return session.to_dict() # type: ignore[attr-defined]
|
|
352
|
+
else:
|
|
353
|
+
# Fallback for dataclass
|
|
354
|
+
from dataclasses import asdict, is_dataclass
|
|
355
|
+
|
|
356
|
+
if is_dataclass(session):
|
|
357
|
+
return asdict(session) # type: ignore[arg-type]
|
|
358
|
+
# If it's already a dict or other type, return as-is
|
|
359
|
+
return session # type: ignore[return-value]
|
|
360
|
+
|
|
361
|
+
logger.debug(f"Session {session_id} not found in ContextEngine")
|
|
362
|
+
return None
|
|
363
|
+
|
|
364
|
+
async def end_session(self, session_id: str, status: str = "completed") -> bool:
|
|
365
|
+
"""
|
|
366
|
+
End a session.
|
|
367
|
+
|
|
368
|
+
Args:
|
|
369
|
+
session_id: Session ID
|
|
370
|
+
status: Final session status (completed, failed, expired)
|
|
371
|
+
|
|
372
|
+
Returns:
|
|
373
|
+
True if session was ended successfully, False otherwise
|
|
374
|
+
|
|
375
|
+
Example:
|
|
376
|
+
success = await adapter.end_session(session_id, status="completed")
|
|
377
|
+
"""
|
|
378
|
+
try:
|
|
379
|
+
await self.context_engine.end_session(session_id, status=status)
|
|
380
|
+
logger.debug(f"Ended session {session_id} with status: {status}")
|
|
381
|
+
return True
|
|
382
|
+
except Exception as e:
|
|
383
|
+
logger.error(f"Failed to end session {session_id}: {e}")
|
|
384
|
+
return False
|
|
385
|
+
|
|
386
|
+
# ==================== Conversation Message Methods ====================
|
|
387
|
+
|
|
388
|
+
def add_conversation_message(self, session_id: str, role: str, content: str, metadata: Optional[Dict] = None) -> None:
|
|
389
|
+
"""
|
|
390
|
+
Add conversation message (sync version - not recommended with ContextEngine).
|
|
391
|
+
|
|
392
|
+
This is a synchronous wrapper that raises NotImplementedError.
|
|
393
|
+
Use aadd_conversation_message() instead for ContextEngine integration.
|
|
394
|
+
|
|
395
|
+
Args:
|
|
396
|
+
session_id: Session ID
|
|
397
|
+
role: Message role (user, assistant, system)
|
|
398
|
+
content: Message content
|
|
399
|
+
metadata: Optional message metadata
|
|
400
|
+
|
|
401
|
+
Raises:
|
|
402
|
+
NotImplementedError: Sync version not supported with ContextEngine
|
|
403
|
+
|
|
404
|
+
Note:
|
|
405
|
+
ContextEngine operations are async. Use aadd_conversation_message() instead.
|
|
406
|
+
"""
|
|
407
|
+
raise NotImplementedError("Synchronous add_conversation_message not supported with ContextEngine. " "Use aadd_conversation_message() instead.")
|
|
408
|
+
|
|
409
|
+
async def aadd_conversation_message(self, session_id: str, role: str, content: str, metadata: Optional[Dict] = None) -> bool:
|
|
410
|
+
"""
|
|
411
|
+
Add conversation message (async version with ContextEngine integration).
|
|
412
|
+
|
|
413
|
+
Args:
|
|
414
|
+
session_id: Session ID
|
|
415
|
+
role: Message role (user, assistant, system)
|
|
416
|
+
content: Message content
|
|
417
|
+
metadata: Optional message metadata
|
|
418
|
+
|
|
419
|
+
Returns:
|
|
420
|
+
True if message was added successfully, False otherwise
|
|
421
|
+
|
|
422
|
+
Example:
|
|
423
|
+
success = await adapter.aadd_conversation_message(
|
|
424
|
+
session_id="session-123",
|
|
425
|
+
role="user",
|
|
426
|
+
content="Hello, how are you?",
|
|
427
|
+
metadata={"source": "web"}
|
|
428
|
+
)
|
|
429
|
+
"""
|
|
430
|
+
try:
|
|
431
|
+
await self.context_engine.add_conversation_message(session_id=session_id, role=role, content=content, metadata=metadata or {})
|
|
432
|
+
logger.debug(f"Added message to session {session_id} (role={role})")
|
|
433
|
+
return True
|
|
434
|
+
except Exception as e:
|
|
435
|
+
logger.error(f"Failed to add message to session {session_id}: {e}")
|
|
436
|
+
return False
|
|
437
|
+
|
|
438
|
+
def get_conversation_history(self, session_id: str, limit: Optional[int] = None) -> List[Dict[str, Any]]:
|
|
439
|
+
"""
|
|
440
|
+
Get conversation history (sync version - not recommended with ContextEngine).
|
|
441
|
+
|
|
442
|
+
This is a synchronous wrapper that raises NotImplementedError.
|
|
443
|
+
Use aget_conversation_history() instead for ContextEngine integration.
|
|
444
|
+
|
|
445
|
+
Args:
|
|
446
|
+
session_id: Session ID
|
|
447
|
+
limit: Optional limit on number of messages
|
|
448
|
+
|
|
449
|
+
Raises:
|
|
450
|
+
NotImplementedError: Sync version not supported with ContextEngine
|
|
451
|
+
|
|
452
|
+
Note:
|
|
453
|
+
ContextEngine operations are async. Use aget_conversation_history() instead.
|
|
454
|
+
"""
|
|
455
|
+
raise NotImplementedError("Synchronous get_conversation_history not supported with ContextEngine. " "Use aget_conversation_history() instead.")
|
|
456
|
+
|
|
457
|
+
async def aget_conversation_history(self, session_id: str, limit: Optional[int] = None) -> List[Dict[str, Any]]:
|
|
458
|
+
"""
|
|
459
|
+
Get conversation history (async version with ContextEngine integration).
|
|
460
|
+
|
|
461
|
+
Args:
|
|
462
|
+
session_id: Session ID
|
|
463
|
+
limit: Optional limit on number of messages (default: 50)
|
|
464
|
+
|
|
465
|
+
Returns:
|
|
466
|
+
List of message dictionaries
|
|
467
|
+
|
|
468
|
+
Example:
|
|
469
|
+
messages = await adapter.aget_conversation_history(
|
|
470
|
+
session_id="session-123",
|
|
471
|
+
limit=10
|
|
472
|
+
)
|
|
473
|
+
for msg in messages:
|
|
474
|
+
print(f"{msg['role']}: {msg['content']}")
|
|
475
|
+
"""
|
|
476
|
+
try:
|
|
477
|
+
messages = await self.context_engine.get_conversation_history(session_id=session_id, limit=limit or 50)
|
|
478
|
+
|
|
479
|
+
# Convert ConversationMessage objects to dictionaries
|
|
480
|
+
result = []
|
|
481
|
+
for msg in messages:
|
|
482
|
+
# messages is List[Dict[str, Any]] from get_conversation_history
|
|
483
|
+
if isinstance(msg, dict):
|
|
484
|
+
result.append(msg)
|
|
485
|
+
else:
|
|
486
|
+
result.append(
|
|
487
|
+
{
|
|
488
|
+
"role": getattr(msg, "role", ""),
|
|
489
|
+
"content": getattr(msg, "content", ""),
|
|
490
|
+
"timestamp": (getattr(msg, "timestamp", "").isoformat() if hasattr(getattr(msg, "timestamp", None), "isoformat") else str(getattr(msg, "timestamp", ""))),
|
|
491
|
+
"metadata": getattr(msg, "metadata", {}),
|
|
492
|
+
}
|
|
493
|
+
)
|
|
494
|
+
|
|
495
|
+
logger.debug(f"Retrieved {len(result)} messages from session {session_id}")
|
|
496
|
+
return result
|
|
497
|
+
except Exception as e:
|
|
498
|
+
logger.error(f"Failed to get conversation history for session {session_id}: {e}")
|
|
499
|
+
return []
|
|
500
|
+
|
|
501
|
+
# ==================== Checkpoint Methods ====================
|
|
502
|
+
|
|
503
|
+
async def store_checkpoint(
|
|
504
|
+
self,
|
|
505
|
+
thread_id: str,
|
|
506
|
+
checkpoint_id: str,
|
|
507
|
+
checkpoint_data: Dict[str, Any],
|
|
508
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
509
|
+
) -> bool:
|
|
510
|
+
"""
|
|
511
|
+
Store a checkpoint in ContextEngine.
|
|
512
|
+
|
|
513
|
+
This is a convenience wrapper around ContextEngine.store_checkpoint()
|
|
514
|
+
that provides consistent error handling and logging.
|
|
515
|
+
|
|
516
|
+
Args:
|
|
517
|
+
thread_id: Thread identifier (typically agent_id or session_id)
|
|
518
|
+
checkpoint_id: Checkpoint identifier (version or timestamp)
|
|
519
|
+
checkpoint_data: Checkpoint data to store
|
|
520
|
+
metadata: Optional metadata for the checkpoint
|
|
521
|
+
|
|
522
|
+
Returns:
|
|
523
|
+
True if checkpoint was stored successfully, False otherwise
|
|
524
|
+
|
|
525
|
+
Example:
|
|
526
|
+
success = await adapter.store_checkpoint(
|
|
527
|
+
thread_id="agent-123",
|
|
528
|
+
checkpoint_id="v1.0",
|
|
529
|
+
checkpoint_data={"state": agent_state},
|
|
530
|
+
metadata={"type": "agent_state", "version": "1.0"}
|
|
531
|
+
)
|
|
532
|
+
"""
|
|
533
|
+
try:
|
|
534
|
+
await self.context_engine.store_checkpoint(
|
|
535
|
+
thread_id=thread_id,
|
|
536
|
+
checkpoint_id=checkpoint_id,
|
|
537
|
+
checkpoint_data=checkpoint_data,
|
|
538
|
+
metadata=metadata or {},
|
|
539
|
+
)
|
|
540
|
+
logger.debug(f"Stored checkpoint {checkpoint_id} for thread {thread_id}")
|
|
541
|
+
return True
|
|
542
|
+
except Exception as e:
|
|
543
|
+
logger.error(f"Failed to store checkpoint {checkpoint_id} for thread {thread_id}: {e}")
|
|
544
|
+
return False
|
|
545
|
+
|
|
546
|
+
async def get_checkpoint(self, thread_id: str, checkpoint_id: Optional[str] = None) -> Optional[Dict[str, Any]]:
|
|
547
|
+
"""
|
|
548
|
+
Get a checkpoint from ContextEngine.
|
|
549
|
+
|
|
550
|
+
This is a convenience wrapper around ContextEngine.get_checkpoint()
|
|
551
|
+
that provides consistent error handling and logging.
|
|
552
|
+
|
|
553
|
+
Args:
|
|
554
|
+
thread_id: Thread identifier (typically agent_id or session_id)
|
|
555
|
+
checkpoint_id: Optional checkpoint identifier (gets latest if None)
|
|
556
|
+
|
|
557
|
+
Returns:
|
|
558
|
+
Checkpoint data dictionary or None if not found
|
|
559
|
+
|
|
560
|
+
Example:
|
|
561
|
+
# Get latest checkpoint
|
|
562
|
+
checkpoint = await adapter.get_checkpoint(thread_id="agent-123")
|
|
563
|
+
|
|
564
|
+
# Get specific checkpoint
|
|
565
|
+
checkpoint = await adapter.get_checkpoint(
|
|
566
|
+
thread_id="agent-123",
|
|
567
|
+
checkpoint_id="v1.0"
|
|
568
|
+
)
|
|
569
|
+
|
|
570
|
+
if checkpoint:
|
|
571
|
+
data = checkpoint.get("data", {})
|
|
572
|
+
metadata = checkpoint.get("metadata", {})
|
|
573
|
+
"""
|
|
574
|
+
try:
|
|
575
|
+
if checkpoint_id is None:
|
|
576
|
+
return None
|
|
577
|
+
checkpoint = await self.context_engine.get_checkpoint(thread_id=thread_id, checkpoint_id=checkpoint_id)
|
|
578
|
+
|
|
579
|
+
if checkpoint:
|
|
580
|
+
logger.debug(f"Retrieved checkpoint {checkpoint_id or 'latest'} for thread {thread_id}")
|
|
581
|
+
return checkpoint
|
|
582
|
+
|
|
583
|
+
logger.debug(f"Checkpoint {checkpoint_id or 'latest'} not found for thread {thread_id}")
|
|
584
|
+
return None
|
|
585
|
+
except Exception as e:
|
|
586
|
+
logger.error(f"Failed to get checkpoint {checkpoint_id or 'latest'} for thread {thread_id}: {e}")
|
|
587
|
+
return None
|