solace-agent-mesh 1.1.0__py3-none-any.whl → 1.3.1__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 solace-agent-mesh might be problematic. Click here for more details.
- solace_agent_mesh/agent/adk/runner.py +18 -12
- solace_agent_mesh/agent/adk/services.py +3 -3
- solace_agent_mesh/agent/adk/setup.py +141 -34
- solace_agent_mesh/agent/protocol/event_handlers.py +27 -21
- solace_agent_mesh/agent/sac/app.py +0 -1
- solace_agent_mesh/agent/sac/component.py +0 -1
- solace_agent_mesh/agent/tools/__init__.py +1 -0
- solace_agent_mesh/agent/tools/dynamic_tool.py +362 -0
- solace_agent_mesh/assets/docs/404.html +3 -3
- solace_agent_mesh/assets/docs/assets/js/42b3f8d8.d97b8e94.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/483cef9a.4e972867.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/55f47984.cf3781c4.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/664b740a.1b744a32.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/75384d09.c193a8f0.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/9a09e75d.d6607c56.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/aba87c2f.071e2d94.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/ae0e903d.4d8dda10.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/c835a94d.146e3186.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/f284c35a.7334119c.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/main.1c79039d.js +2 -0
- solace_agent_mesh/assets/docs/assets/js/runtime~main.858117b7.js +1 -0
- solace_agent_mesh/assets/docs/docs/documentation/Enterprise/installation/index.html +29 -0
- solace_agent_mesh/assets/docs/docs/documentation/Enterprise/single-sign-on/index.html +25 -0
- solace_agent_mesh/assets/docs/docs/documentation/{migration-guides/a2a-upgrade-to-0.3.0/a2a-gateway-upgrade-to-0.3.0/index.html → Migrations/A2A Upgrade To 0.3.0/a2a-gateway-upgrade-to-0.3.0/index.html } +6 -6
- solace_agent_mesh/assets/docs/docs/documentation/{migration-guides/a2a-upgrade-to-0.3.0/a2a-technical-migration-map/index.html → Migrations/A2A Upgrade To 0.3.0/a2a-technical-migration-map/index.html } +6 -6
- solace_agent_mesh/assets/docs/docs/documentation/concepts/agents/index.html +19 -27
- solace_agent_mesh/assets/docs/docs/documentation/concepts/architecture/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/concepts/cli/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/concepts/gateways/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/concepts/orchestrator/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/concepts/plugins/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/deployment/debugging/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/deployment/deploy/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/deployment/observability/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/component-overview/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/configurations/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/installation/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/introduction/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/quick-start/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/tutorials/bedrock-agents/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/tutorials/custom-agent/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/tutorials/event-mesh-gateway/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/tutorials/mcp-integration/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/tutorials/mongodb-integration/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/tutorials/rag-integration/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/tutorials/rest-gateway/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/tutorials/slack-integration/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/tutorials/sql-database/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/artifact-management/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/audio-tools/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/data-analysis-tools/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/embeds/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/user-guide/create-agents/index.html +5 -4
- solace_agent_mesh/assets/docs/docs/documentation/user-guide/create-gateways/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/user-guide/creating-python-tools/index.html +63 -0
- solace_agent_mesh/assets/docs/docs/documentation/user-guide/creating-service-providers/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/user-guide/solace-ai-connector/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/user-guide/structure/index.html +4 -4
- solace_agent_mesh/assets/docs/lunr-index-1757531604543.json +1 -0
- solace_agent_mesh/assets/docs/lunr-index.json +1 -1
- solace_agent_mesh/assets/docs/search-doc-1757531604543.json +1 -0
- solace_agent_mesh/assets/docs/search-doc.json +1 -1
- solace_agent_mesh/assets/docs/sitemap.xml +1 -1
- solace_agent_mesh/cli/__init__.py +1 -1
- solace_agent_mesh/cli/commands/add_cmd/agent_cmd.py +125 -48
- solace_agent_mesh/cli/commands/eval_cmd.py +14 -0
- solace_agent_mesh/cli/commands/init_cmd/__init__.py +53 -31
- solace_agent_mesh/cli/commands/init_cmd/database_step.py +91 -0
- solace_agent_mesh/cli/commands/init_cmd/env_step.py +19 -8
- solace_agent_mesh/cli/commands/init_cmd/orchestrator_step.py +80 -25
- solace_agent_mesh/cli/commands/init_cmd/web_init_step.py +32 -10
- solace_agent_mesh/cli/commands/init_cmd/webui_gateway_step.py +74 -15
- solace_agent_mesh/cli/commands/plugin_cmd/create_cmd.py +0 -2
- solace_agent_mesh/cli/commands/run_cmd.py +5 -3
- solace_agent_mesh/cli/utils.py +68 -12
- solace_agent_mesh/client/webui/frontend/static/assets/authCallback-CAX9u8a7.js +1 -0
- solace_agent_mesh/client/webui/frontend/static/assets/client-DXU9SPI5.js +25 -0
- solace_agent_mesh/client/webui/frontend/static/assets/main-C03yrETa.css +1 -0
- solace_agent_mesh/client/webui/frontend/static/assets/main-C1k9E0aC.js +339 -0
- solace_agent_mesh/client/webui/frontend/static/assets/vendor-B0BEKoAR.js +390 -0
- solace_agent_mesh/client/webui/frontend/static/auth-callback.html +3 -2
- solace_agent_mesh/client/webui/frontend/static/index.html +4 -3
- solace_agent_mesh/common/utils/embeds/resolver.py +1 -0
- solace_agent_mesh/config_portal/backend/common.py +2 -2
- solace_agent_mesh/config_portal/frontend/static/client/assets/_index-bFMKlzKf.js +98 -0
- solace_agent_mesh/config_portal/frontend/static/client/assets/{manifest-d845808d.js → manifest-89db7c30.js} +1 -1
- solace_agent_mesh/config_portal/frontend/static/client/index.html +1 -1
- solace_agent_mesh/evaluation/message_organizer.py +35 -56
- solace_agent_mesh/evaluation/run.py +26 -5
- solace_agent_mesh/evaluation/subscriber.py +35 -10
- solace_agent_mesh/evaluation/summary_builder.py +27 -34
- solace_agent_mesh/gateway/http_sse/ARCHITECTURE_GUIDE.md +676 -0
- solace_agent_mesh/gateway/http_sse/alembic/env.py +85 -0
- solace_agent_mesh/gateway/http_sse/alembic/script.py.mako +28 -0
- solace_agent_mesh/gateway/http_sse/alembic/versions/b1c2d3e4f5g6_add_database_indexes.py +83 -0
- solace_agent_mesh/gateway/http_sse/alembic/versions/d5b3f8f2e9a0_create_initial_database.py +58 -0
- solace_agent_mesh/gateway/http_sse/alembic.ini +147 -0
- solace_agent_mesh/gateway/http_sse/api/__init__.py +11 -0
- solace_agent_mesh/gateway/http_sse/api/controllers/__init__.py +9 -0
- solace_agent_mesh/gateway/http_sse/api/controllers/session_controller.py +355 -0
- solace_agent_mesh/gateway/http_sse/api/controllers/task_controller.py +279 -0
- solace_agent_mesh/gateway/http_sse/api/controllers/user_controller.py +35 -0
- solace_agent_mesh/gateway/http_sse/api/dto/__init__.py +10 -0
- solace_agent_mesh/gateway/http_sse/api/dto/requests/__init__.py +37 -0
- solace_agent_mesh/gateway/http_sse/api/dto/requests/session_requests.py +49 -0
- solace_agent_mesh/gateway/http_sse/api/dto/requests/task_requests.py +66 -0
- solace_agent_mesh/gateway/http_sse/api/dto/responses/__init__.py +43 -0
- solace_agent_mesh/gateway/http_sse/api/dto/responses/session_responses.py +68 -0
- solace_agent_mesh/gateway/http_sse/api/dto/responses/task_responses.py +74 -0
- solace_agent_mesh/gateway/http_sse/app.py +31 -1
- solace_agent_mesh/gateway/http_sse/application/__init__.py +3 -0
- solace_agent_mesh/gateway/http_sse/application/services/__init__.py +3 -0
- solace_agent_mesh/gateway/http_sse/application/services/session_service.py +135 -0
- solace_agent_mesh/gateway/http_sse/component.py +224 -62
- solace_agent_mesh/gateway/http_sse/dependencies.py +148 -45
- solace_agent_mesh/gateway/http_sse/domain/entities/__init__.py +3 -0
- solace_agent_mesh/gateway/http_sse/domain/entities/session.py +90 -0
- solace_agent_mesh/gateway/http_sse/domain/repositories/__init__.py +3 -0
- solace_agent_mesh/gateway/http_sse/domain/repositories/session_repository.py +54 -0
- solace_agent_mesh/gateway/http_sse/infrastructure/__init__.py +4 -0
- solace_agent_mesh/gateway/http_sse/infrastructure/dependency_injection/__init__.py +3 -0
- solace_agent_mesh/gateway/http_sse/infrastructure/dependency_injection/container.py +123 -0
- solace_agent_mesh/gateway/http_sse/infrastructure/persistence/__init__.py +4 -0
- solace_agent_mesh/gateway/http_sse/infrastructure/persistence/database_persistence_service.py +16 -0
- solace_agent_mesh/gateway/http_sse/infrastructure/persistence/database_service.py +119 -0
- solace_agent_mesh/gateway/http_sse/infrastructure/persistence/models.py +31 -0
- solace_agent_mesh/gateway/http_sse/infrastructure/persistence_service.py +12 -0
- solace_agent_mesh/gateway/http_sse/infrastructure/repositories/__init__.py +3 -0
- solace_agent_mesh/gateway/http_sse/infrastructure/repositories/session_repository.py +174 -0
- solace_agent_mesh/gateway/http_sse/main.py +291 -87
- solace_agent_mesh/gateway/http_sse/routers/{agents.py → agent_cards.py} +7 -7
- solace_agent_mesh/gateway/http_sse/routers/artifacts.py +121 -54
- solace_agent_mesh/gateway/http_sse/routers/config.py +3 -1
- solace_agent_mesh/gateway/http_sse/routers/tasks.py +83 -2
- solace_agent_mesh/gateway/http_sse/routers/visualization.py +7 -7
- solace_agent_mesh/gateway/http_sse/services/{agent_service.py → agent_card_service.py} +19 -19
- solace_agent_mesh/gateway/http_sse/session_manager.py +64 -30
- solace_agent_mesh/gateway/http_sse/shared/__init__.py +9 -0
- solace_agent_mesh/gateway/http_sse/shared/auth_utils.py +29 -0
- solace_agent_mesh/gateway/http_sse/shared/enums.py +45 -0
- solace_agent_mesh/gateway/http_sse/shared/types.py +45 -0
- solace_agent_mesh/templates/shared_config.yaml +4 -5
- solace_agent_mesh/templates/webui.yaml +8 -10
- {solace_agent_mesh-1.1.0.dist-info → solace_agent_mesh-1.3.1.dist-info}/METADATA +5 -3
- {solace_agent_mesh-1.1.0.dist-info → solace_agent_mesh-1.3.1.dist-info}/RECORD +150 -104
- solace_agent_mesh/assets/docs/assets/js/42b3f8d8.8ccb9901.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/55f47984.c484bf96.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/6e0db977.39a79ca9.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/75384d09.bf78fbdb.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/90dd9cf6.88f385ea.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/aba87c2f.76376d7c.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/f284c35a.fb68323a.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/main.a75ecc0d.js +0 -2
- solace_agent_mesh/assets/docs/assets/js/runtime~main.458efb1d.js +0 -1
- solace_agent_mesh/assets/docs/lunr-index-1756992446316.json +0 -1
- solace_agent_mesh/assets/docs/search-doc-1756992446316.json +0 -1
- solace_agent_mesh/client/webui/frontend/static/assets/authCallback-BmF2l6vg.js +0 -1
- solace_agent_mesh/client/webui/frontend/static/assets/client-D881Dttc.js +0 -49
- solace_agent_mesh/client/webui/frontend/static/assets/main-C0jZjYa8.js +0 -699
- solace_agent_mesh/client/webui/frontend/static/assets/main-CCeG324-.css +0 -1
- solace_agent_mesh/config_portal/frontend/static/client/assets/_index-Bym6YkMd.js +0 -98
- solace_agent_mesh/gateway/http_sse/routers/sessions.py +0 -85
- solace_agent_mesh/gateway/http_sse/routers/users.py +0 -59
- /solace_agent_mesh/assets/docs/assets/js/{main.a75ecc0d.js.LICENSE.txt → main.1c79039d.js.LICENSE.txt} +0 -0
- {solace_agent_mesh-1.1.0.dist-info → solace_agent_mesh-1.3.1.dist-info}/WHEEL +0 -0
- {solace_agent_mesh-1.1.0.dist-info → solace_agent_mesh-1.3.1.dist-info}/entry_points.txt +0 -0
- {solace_agent_mesh-1.1.0.dist-info → solace_agent_mesh-1.3.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from collections.abc import Generator
|
|
3
|
+
from contextlib import contextmanager
|
|
4
|
+
|
|
5
|
+
from sqlalchemy import create_engine, event
|
|
6
|
+
from sqlalchemy.orm import Session, sessionmaker
|
|
7
|
+
|
|
8
|
+
from .models import Base
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def get_database_type(database_url: str) -> str:
|
|
12
|
+
"""Get the database type from a database URL."""
|
|
13
|
+
if database_url.startswith("sqlite"):
|
|
14
|
+
return "sqlite"
|
|
15
|
+
elif database_url.startswith("postgresql"):
|
|
16
|
+
return "postgresql"
|
|
17
|
+
else:
|
|
18
|
+
return "unknown"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class DatabaseService:
|
|
22
|
+
def __init__(self, database_url: str):
|
|
23
|
+
self.database_url = database_url
|
|
24
|
+
self.logger = logging.getLogger(__name__)
|
|
25
|
+
|
|
26
|
+
if database_url.startswith("sqlite"):
|
|
27
|
+
self._setup_sqlite_engine(database_url)
|
|
28
|
+
elif database_url.startswith("postgresql"):
|
|
29
|
+
self._setup_postgresql_engine(database_url)
|
|
30
|
+
else:
|
|
31
|
+
# Fallback for other databases
|
|
32
|
+
self._setup_generic_engine(database_url)
|
|
33
|
+
|
|
34
|
+
self.SessionLocal = sessionmaker(
|
|
35
|
+
autocommit=False, autoflush=False, bind=self.engine
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
def _setup_sqlite_engine(self, database_url: str):
|
|
39
|
+
"""Configure SQLite-specific engine settings."""
|
|
40
|
+
self.engine = create_engine(
|
|
41
|
+
database_url,
|
|
42
|
+
echo=False,
|
|
43
|
+
connect_args={
|
|
44
|
+
"check_same_thread": False,
|
|
45
|
+
},
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
@event.listens_for(self.engine, "connect")
|
|
49
|
+
def set_sqlite_pragma(dbapi_connection, connection_record):
|
|
50
|
+
cursor = dbapi_connection.cursor()
|
|
51
|
+
cursor.execute("PRAGMA foreign_keys=ON")
|
|
52
|
+
cursor.close()
|
|
53
|
+
|
|
54
|
+
def _setup_postgresql_engine(self, database_url: str):
|
|
55
|
+
"""Configure PostgreSQL-specific engine settings."""
|
|
56
|
+
try:
|
|
57
|
+
import psycopg2
|
|
58
|
+
except ImportError:
|
|
59
|
+
raise ImportError(
|
|
60
|
+
"PostgreSQL support requires psycopg2. Install with: "
|
|
61
|
+
"pip install 'solace-agent-mesh[postgresql]'"
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
self.engine = create_engine(
|
|
65
|
+
database_url,
|
|
66
|
+
pool_size=10,
|
|
67
|
+
max_overflow=20,
|
|
68
|
+
pool_timeout=30,
|
|
69
|
+
pool_recycle=3600,
|
|
70
|
+
pool_pre_ping=True,
|
|
71
|
+
echo=False,
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
def _setup_generic_engine(self, database_url: str):
|
|
75
|
+
"""Configure generic database engine settings."""
|
|
76
|
+
self.engine = create_engine(
|
|
77
|
+
database_url,
|
|
78
|
+
pool_size=10,
|
|
79
|
+
max_overflow=20,
|
|
80
|
+
pool_timeout=30,
|
|
81
|
+
pool_recycle=3600,
|
|
82
|
+
pool_pre_ping=True,
|
|
83
|
+
echo=False,
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
def create_tables(self):
|
|
87
|
+
Base.metadata.create_all(bind=self.engine)
|
|
88
|
+
|
|
89
|
+
@contextmanager
|
|
90
|
+
def session_scope(self) -> Generator[Session, None, None]:
|
|
91
|
+
session = self.SessionLocal()
|
|
92
|
+
try:
|
|
93
|
+
yield session
|
|
94
|
+
session.commit()
|
|
95
|
+
except Exception as e:
|
|
96
|
+
session.rollback()
|
|
97
|
+
self.logger.error(f"Database transaction failed: {e}")
|
|
98
|
+
raise
|
|
99
|
+
finally:
|
|
100
|
+
session.close()
|
|
101
|
+
|
|
102
|
+
@contextmanager
|
|
103
|
+
def read_only_session(self) -> Generator[Session, None, None]:
|
|
104
|
+
session = self.SessionLocal()
|
|
105
|
+
try:
|
|
106
|
+
yield session
|
|
107
|
+
except Exception as e:
|
|
108
|
+
session.rollback()
|
|
109
|
+
self.logger.error(f"Database read operation failed: {e}")
|
|
110
|
+
raise
|
|
111
|
+
finally:
|
|
112
|
+
session.close()
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
database_service: DatabaseService = None
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def get_database_service() -> DatabaseService:
|
|
119
|
+
return database_service
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
from sqlalchemy import Column, DateTime, ForeignKey, String, Text
|
|
2
|
+
from sqlalchemy.orm import declarative_base, relationship
|
|
3
|
+
from sqlalchemy.sql import func
|
|
4
|
+
|
|
5
|
+
Base = declarative_base()
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class SessionModel(Base):
|
|
9
|
+
__tablename__ = "sessions"
|
|
10
|
+
id = Column(String, primary_key=True)
|
|
11
|
+
name = Column(String, nullable=True)
|
|
12
|
+
user_id = Column(String, nullable=False)
|
|
13
|
+
agent_id = Column(String, nullable=True)
|
|
14
|
+
created_at = Column(DateTime, default=func.now())
|
|
15
|
+
updated_at = Column(DateTime, default=func.now(), onupdate=func.now())
|
|
16
|
+
messages = relationship(
|
|
17
|
+
"MessageModel", back_populates="session", cascade="all, delete-orphan"
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class MessageModel(Base):
|
|
22
|
+
__tablename__ = "chat_messages"
|
|
23
|
+
id = Column(String, primary_key=True)
|
|
24
|
+
session_id = Column(
|
|
25
|
+
String, ForeignKey("sessions.id", ondelete="CASCADE"), nullable=False
|
|
26
|
+
)
|
|
27
|
+
message = Column(Text, nullable=False)
|
|
28
|
+
created_at = Column(DateTime, default=func.now())
|
|
29
|
+
sender_type = Column(String(50))
|
|
30
|
+
sender_name = Column(String(255))
|
|
31
|
+
session = relationship("SessionModel", back_populates="messages")
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from .dependency_injection.container import ApplicationContainer
|
|
2
|
+
from .persistence.database_service import DatabaseService
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class PersistenceService:
|
|
6
|
+
def __init__(self, database_url: str):
|
|
7
|
+
self.db_service = DatabaseService(database_url)
|
|
8
|
+
self.container = ApplicationContainer(database_url)
|
|
9
|
+
|
|
10
|
+
@property
|
|
11
|
+
def engine(self):
|
|
12
|
+
return self.db_service.engine
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
from ...domain.entities.session import Message, Session
|
|
2
|
+
from ...domain.repositories.session_repository import (
|
|
3
|
+
IMessageRepository,
|
|
4
|
+
ISessionRepository,
|
|
5
|
+
)
|
|
6
|
+
from ...shared.enums import SenderType, SessionStatus
|
|
7
|
+
from ...shared.types import PaginationInfo, SessionId, UserId
|
|
8
|
+
from ..persistence.database_service import DatabaseService
|
|
9
|
+
from ..persistence.models import MessageModel, SessionModel
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class SessionRepository(ISessionRepository):
|
|
13
|
+
def __init__(self, db_service: DatabaseService):
|
|
14
|
+
self.db_service = db_service
|
|
15
|
+
|
|
16
|
+
def get_by_id(self, session_id: SessionId) -> Session | None:
|
|
17
|
+
with self.db_service.read_only_session() as session:
|
|
18
|
+
model = (
|
|
19
|
+
session.query(SessionModel)
|
|
20
|
+
.filter(SessionModel.id == session_id)
|
|
21
|
+
.first()
|
|
22
|
+
)
|
|
23
|
+
return self._model_to_entity(model) if model else None
|
|
24
|
+
|
|
25
|
+
def get_by_user_id(
|
|
26
|
+
self, user_id: UserId, pagination: PaginationInfo | None = None
|
|
27
|
+
) -> list[Session]:
|
|
28
|
+
with self.db_service.read_only_session() as session:
|
|
29
|
+
query = session.query(SessionModel).filter(SessionModel.user_id == user_id)
|
|
30
|
+
|
|
31
|
+
if pagination:
|
|
32
|
+
offset = (pagination.page - 1) * pagination.page_size
|
|
33
|
+
query = query.offset(offset).limit(pagination.page_size)
|
|
34
|
+
|
|
35
|
+
models = query.order_by(SessionModel.updated_at.desc()).all()
|
|
36
|
+
return [self._model_to_entity(model) for model in models]
|
|
37
|
+
|
|
38
|
+
def get_user_session(
|
|
39
|
+
self, session_id: SessionId, user_id: UserId
|
|
40
|
+
) -> Session | None:
|
|
41
|
+
with self.db_service.read_only_session() as session:
|
|
42
|
+
model = (
|
|
43
|
+
session.query(SessionModel)
|
|
44
|
+
.filter(SessionModel.id == session_id, SessionModel.user_id == user_id)
|
|
45
|
+
.first()
|
|
46
|
+
)
|
|
47
|
+
return self._model_to_entity(model) if model else None
|
|
48
|
+
|
|
49
|
+
def create(self, session_entity: Session) -> Session:
|
|
50
|
+
with self.db_service.session_scope() as session:
|
|
51
|
+
model = SessionModel(
|
|
52
|
+
id=session_entity.id,
|
|
53
|
+
user_id=session_entity.user_id,
|
|
54
|
+
name=session_entity.name,
|
|
55
|
+
agent_id=session_entity.agent_id,
|
|
56
|
+
created_at=session_entity.created_at,
|
|
57
|
+
updated_at=session_entity.updated_at,
|
|
58
|
+
)
|
|
59
|
+
session.add(model)
|
|
60
|
+
session.flush()
|
|
61
|
+
session.refresh(model)
|
|
62
|
+
return self._model_to_entity(model)
|
|
63
|
+
|
|
64
|
+
def update(self, session_entity: Session) -> Session | None:
|
|
65
|
+
with self.db_service.session_scope() as session:
|
|
66
|
+
model = (
|
|
67
|
+
session.query(SessionModel)
|
|
68
|
+
.filter(
|
|
69
|
+
SessionModel.id == session_entity.id,
|
|
70
|
+
SessionModel.user_id == session_entity.user_id,
|
|
71
|
+
)
|
|
72
|
+
.first()
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
if not model:
|
|
76
|
+
return None
|
|
77
|
+
|
|
78
|
+
model.name = session_entity.name
|
|
79
|
+
model.agent_id = session_entity.agent_id
|
|
80
|
+
model.updated_at = session_entity.updated_at
|
|
81
|
+
|
|
82
|
+
session.flush()
|
|
83
|
+
session.refresh(model)
|
|
84
|
+
return self._model_to_entity(model)
|
|
85
|
+
|
|
86
|
+
def delete(self, session_id: SessionId, user_id: UserId) -> bool:
|
|
87
|
+
with self.db_service.session_scope() as session:
|
|
88
|
+
model = (
|
|
89
|
+
session.query(SessionModel)
|
|
90
|
+
.filter(SessionModel.id == session_id, SessionModel.user_id == user_id)
|
|
91
|
+
.first()
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
if not model:
|
|
95
|
+
return False
|
|
96
|
+
|
|
97
|
+
session.delete(model)
|
|
98
|
+
return True
|
|
99
|
+
|
|
100
|
+
def exists(self, session_id: SessionId) -> bool:
|
|
101
|
+
with self.db_service.read_only_session() as session:
|
|
102
|
+
return (
|
|
103
|
+
session.query(SessionModel)
|
|
104
|
+
.filter(SessionModel.id == session_id)
|
|
105
|
+
.first()
|
|
106
|
+
is not None
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
def _model_to_entity(self, model: SessionModel) -> Session:
|
|
110
|
+
return Session(
|
|
111
|
+
id=model.id,
|
|
112
|
+
user_id=model.user_id,
|
|
113
|
+
name=model.name,
|
|
114
|
+
agent_id=model.agent_id,
|
|
115
|
+
status=SessionStatus.ACTIVE,
|
|
116
|
+
created_at=model.created_at,
|
|
117
|
+
updated_at=model.updated_at,
|
|
118
|
+
last_activity=model.updated_at,
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
class MessageRepository(IMessageRepository):
|
|
123
|
+
def __init__(self, db_service: DatabaseService):
|
|
124
|
+
self.db_service = db_service
|
|
125
|
+
|
|
126
|
+
def get_by_session_id(
|
|
127
|
+
self, session_id: SessionId, pagination: PaginationInfo | None = None
|
|
128
|
+
) -> list[Message]:
|
|
129
|
+
with self.db_service.read_only_session() as session:
|
|
130
|
+
query = session.query(MessageModel).filter(
|
|
131
|
+
MessageModel.session_id == session_id
|
|
132
|
+
)
|
|
133
|
+
query = query.order_by(MessageModel.created_at.asc())
|
|
134
|
+
|
|
135
|
+
if pagination:
|
|
136
|
+
offset = (pagination.page - 1) * pagination.page_size
|
|
137
|
+
query = query.offset(offset).limit(pagination.page_size)
|
|
138
|
+
|
|
139
|
+
models = query.all()
|
|
140
|
+
return [self._model_to_entity(model) for model in models]
|
|
141
|
+
|
|
142
|
+
def create(self, message_entity: Message) -> Message:
|
|
143
|
+
with self.db_service.session_scope() as session:
|
|
144
|
+
model = MessageModel(
|
|
145
|
+
id=message_entity.id,
|
|
146
|
+
session_id=message_entity.session_id,
|
|
147
|
+
message=message_entity.message,
|
|
148
|
+
sender_type=message_entity.sender_type.value,
|
|
149
|
+
sender_name=message_entity.sender_name,
|
|
150
|
+
created_at=message_entity.created_at,
|
|
151
|
+
)
|
|
152
|
+
session.add(model)
|
|
153
|
+
session.flush()
|
|
154
|
+
session.refresh(model)
|
|
155
|
+
return self._model_to_entity(model)
|
|
156
|
+
|
|
157
|
+
def delete_by_session_id(self, session_id: SessionId) -> bool:
|
|
158
|
+
with self.db_service.session_scope() as session:
|
|
159
|
+
deleted_count = (
|
|
160
|
+
session.query(MessageModel)
|
|
161
|
+
.filter(MessageModel.session_id == session_id)
|
|
162
|
+
.delete()
|
|
163
|
+
)
|
|
164
|
+
return deleted_count > 0
|
|
165
|
+
|
|
166
|
+
def _model_to_entity(self, model: MessageModel) -> Message:
|
|
167
|
+
return Message(
|
|
168
|
+
id=model.id,
|
|
169
|
+
session_id=model.session_id,
|
|
170
|
+
message=model.message,
|
|
171
|
+
sender_type=SenderType(model.sender_type),
|
|
172
|
+
sender_name=model.sender_name,
|
|
173
|
+
created_at=model.created_at,
|
|
174
|
+
)
|