solace-agent-mesh 1.5.1__py3-none-any.whl → 1.6.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/callbacks.py +0 -5
- solace_agent_mesh/agent/adk/models/lite_llm.py +123 -8
- solace_agent_mesh/agent/adk/models/oauth2_token_manager.py +245 -0
- solace_agent_mesh/agent/protocol/event_handlers.py +213 -31
- solace_agent_mesh/agent/proxies/__init__.py +0 -0
- solace_agent_mesh/agent/proxies/a2a/__init__.py +3 -0
- solace_agent_mesh/agent/proxies/a2a/app.py +55 -0
- solace_agent_mesh/agent/proxies/a2a/component.py +1115 -0
- solace_agent_mesh/agent/proxies/a2a/config.py +140 -0
- solace_agent_mesh/agent/proxies/a2a/oauth_token_cache.py +104 -0
- solace_agent_mesh/agent/proxies/base/__init__.py +3 -0
- solace_agent_mesh/agent/proxies/base/app.py +99 -0
- solace_agent_mesh/agent/proxies/base/component.py +650 -0
- solace_agent_mesh/agent/proxies/base/config.py +85 -0
- solace_agent_mesh/agent/proxies/base/proxy_task_context.py +17 -0
- solace_agent_mesh/agent/sac/app.py +58 -5
- solace_agent_mesh/agent/sac/component.py +238 -75
- solace_agent_mesh/agent/sac/task_execution_context.py +46 -0
- solace_agent_mesh/agent/tools/audio_tools.py +125 -8
- solace_agent_mesh/agent/tools/web_tools.py +10 -5
- solace_agent_mesh/agent/utils/artifact_helpers.py +141 -3
- solace_agent_mesh/assets/docs/404.html +3 -3
- solace_agent_mesh/assets/docs/assets/js/5c2bd65f.eda4bcb2.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/6ad8f0bd.f4b15f3b.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/71da7b71.38583438.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/77cf947d.48cb18a2.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/924ffdeb.8095e148.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/9e9d0a82.570c057b.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/{ad71b5ed.60668e9e.js → ad71b5ed.af3ecfd1.js} +1 -1
- solace_agent_mesh/assets/docs/assets/js/ceb2a7a6.5d92d7d0.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/{da0b5bad.9d369087.js → da0b5bad.d08a9466.js} +1 -1
- solace_agent_mesh/assets/docs/assets/js/db924877.e98d12a1.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/de915948.27d6b065.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/{e3d9abda.2b916f9e.js → e3d9abda.6b9493d0.js} +1 -1
- solace_agent_mesh/assets/docs/assets/js/e6f9706b.e74a984d.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/f284c35a.42f59cdd.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/ff4d71f2.15b02f97.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/{main.bd3c34f3.js → main.b12eac43.js} +2 -2
- solace_agent_mesh/assets/docs/assets/js/runtime~main.e268214e.js +1 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/agents/index.html +15 -4
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/artifact-management/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/audio-tools/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/data-analysis-tools/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/embeds/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/components/cli/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/components/gateways/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/components/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/components/orchestrator/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/components/plugins/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/components/proxies/index.html +262 -0
- solace_agent_mesh/assets/docs/docs/documentation/deploying/debugging/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/deploying/deployment-options/index.html +31 -3
- solace_agent_mesh/assets/docs/docs/documentation/deploying/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/deploying/observability/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/developing/create-agents/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/developing/create-gateways/index.html +5 -5
- solace_agent_mesh/assets/docs/docs/documentation/developing/creating-python-tools/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/developing/creating-service-providers/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/developing/evaluations/index.html +135 -0
- solace_agent_mesh/assets/docs/docs/documentation/developing/index.html +6 -4
- solace_agent_mesh/assets/docs/docs/documentation/developing/structure/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/bedrock-agents/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/custom-agent/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/event-mesh-gateway/index.html +5 -5
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/mcp-integration/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/mongodb-integration/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/rag-integration/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/rest-gateway/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/slack-integration/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/sql-database/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/installation/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/rbac-setup-guide/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/single-sign-on/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/architecture/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/introduction/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/try-agent-mesh/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/configurations/index.html +6 -5
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/installation/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/large_language_models/index.html +100 -3
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/run-project/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-gateway-upgrade-to-0.3.0/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-technical-migration-map/index.html +3 -3
- solace_agent_mesh/assets/docs/lunr-index-1761248203150.json +1 -0
- solace_agent_mesh/assets/docs/lunr-index.json +1 -1
- solace_agent_mesh/assets/docs/search-doc-1761248203150.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 +2 -69
- solace_agent_mesh/cli/commands/eval_cmd.py +11 -49
- solace_agent_mesh/cli/commands/init_cmd/__init__.py +0 -5
- solace_agent_mesh/cli/commands/init_cmd/env_step.py +10 -12
- solace_agent_mesh/cli/commands/init_cmd/orchestrator_step.py +9 -61
- solace_agent_mesh/cli/commands/init_cmd/webui_gateway_step.py +9 -49
- solace_agent_mesh/cli/commands/plugin_cmd/add_cmd.py +1 -2
- solace_agent_mesh/client/webui/frontend/static/assets/{authCallback-DwrxZE0E.js → authCallback-BTf6dqwp.js} +1 -1
- solace_agent_mesh/client/webui/frontend/static/assets/{client-DarGQzyw.js → client-CaY59VuC.js} +1 -1
- solace_agent_mesh/client/webui/frontend/static/assets/main-B32noGmR.js +342 -0
- solace_agent_mesh/client/webui/frontend/static/assets/main-DHJKSW1S.css +1 -0
- solace_agent_mesh/client/webui/frontend/static/assets/{vendor-BKIeiHj_.js → vendor-BEmvJSYz.js} +1 -1
- solace_agent_mesh/client/webui/frontend/static/auth-callback.html +3 -3
- solace_agent_mesh/client/webui/frontend/static/index.html +4 -4
- solace_agent_mesh/common/a2a/__init__.py +24 -0
- solace_agent_mesh/common/a2a/artifact.py +39 -0
- solace_agent_mesh/common/a2a/events.py +29 -0
- solace_agent_mesh/common/a2a/message.py +68 -0
- solace_agent_mesh/common/a2a/protocol.py +151 -1
- solace_agent_mesh/common/agent_registry.py +83 -3
- solace_agent_mesh/common/constants.py +3 -1
- solace_agent_mesh/common/sac/sam_component_base.py +383 -4
- solace_agent_mesh/common/utils/pydantic_utils.py +12 -0
- solace_agent_mesh/config_portal/backend/common.py +1 -1
- solace_agent_mesh/config_portal/frontend/static/client/assets/_index-ByU1X1HD.js +98 -0
- solace_agent_mesh/config_portal/frontend/static/client/assets/{manifest-44d62be6.js → manifest-61038fc6.js} +1 -1
- solace_agent_mesh/config_portal/frontend/static/client/index.html +1 -1
- solace_agent_mesh/evaluation/evaluator.py +128 -104
- solace_agent_mesh/evaluation/message_organizer.py +116 -110
- solace_agent_mesh/evaluation/report_data_processor.py +84 -86
- solace_agent_mesh/evaluation/report_generator.py +73 -79
- solace_agent_mesh/evaluation/run.py +421 -235
- solace_agent_mesh/evaluation/shared/__init__.py +92 -0
- solace_agent_mesh/evaluation/shared/constants.py +47 -0
- solace_agent_mesh/evaluation/shared/exceptions.py +50 -0
- solace_agent_mesh/evaluation/shared/helpers.py +35 -0
- solace_agent_mesh/evaluation/shared/test_case_loader.py +167 -0
- solace_agent_mesh/evaluation/shared/test_suite_loader.py +280 -0
- solace_agent_mesh/evaluation/subscriber.py +111 -232
- solace_agent_mesh/evaluation/summary_builder.py +227 -117
- solace_agent_mesh/gateway/base/app.py +16 -1
- solace_agent_mesh/gateway/base/component.py +112 -39
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251015_add_session_performance_indexes.py +70 -0
- solace_agent_mesh/gateway/http_sse/component.py +99 -3
- solace_agent_mesh/gateway/http_sse/dependencies.py +4 -4
- solace_agent_mesh/gateway/http_sse/main.py +1 -0
- solace_agent_mesh/gateway/http_sse/repository/chat_task_repository.py +12 -13
- solace_agent_mesh/gateway/http_sse/repository/feedback_repository.py +15 -18
- solace_agent_mesh/gateway/http_sse/repository/interfaces.py +25 -18
- solace_agent_mesh/gateway/http_sse/repository/session_repository.py +30 -26
- solace_agent_mesh/gateway/http_sse/repository/task_repository.py +35 -44
- solace_agent_mesh/gateway/http_sse/routers/agent_cards.py +4 -3
- solace_agent_mesh/gateway/http_sse/routers/artifacts.py +95 -203
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/session_responses.py +4 -3
- solace_agent_mesh/gateway/http_sse/routers/sessions.py +2 -2
- solace_agent_mesh/gateway/http_sse/routers/tasks.py +33 -41
- solace_agent_mesh/gateway/http_sse/routers/users.py +47 -1
- solace_agent_mesh/gateway/http_sse/routers/visualization.py +17 -11
- solace_agent_mesh/gateway/http_sse/services/data_retention_service.py +4 -4
- solace_agent_mesh/gateway/http_sse/services/feedback_service.py +51 -43
- solace_agent_mesh/gateway/http_sse/services/session_service.py +20 -20
- solace_agent_mesh/gateway/http_sse/services/task_logger_service.py +8 -8
- solace_agent_mesh/gateway/http_sse/shared/base_repository.py +45 -71
- solace_agent_mesh/gateway/http_sse/shared/types.py +0 -18
- solace_agent_mesh/templates/gateway_config_template.yaml +0 -5
- solace_agent_mesh/templates/logging_config_template.ini +10 -6
- solace_agent_mesh/templates/plugin_gateway_config_template.yaml +0 -3
- solace_agent_mesh/templates/shared_config.yaml +40 -0
- {solace_agent_mesh-1.5.1.dist-info → solace_agent_mesh-1.6.1.dist-info}/METADATA +47 -21
- {solace_agent_mesh-1.5.1.dist-info → solace_agent_mesh-1.6.1.dist-info}/RECORD +166 -145
- solace_agent_mesh/assets/docs/assets/js/5c2bd65f.e49689dd.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/6ad8f0bd.39d5851d.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/71da7b71.804d6567.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/77cf947d.64c9bd6c.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/9e9d0a82.dd810042.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/db924877.cbc66f02.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/de915948.139b4b9c.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/e6f9706b.582a78ca.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/f284c35a.5766a13d.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/ff4d71f2.9c0297a6.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/runtime~main.18dc45dd.js +0 -1
- solace_agent_mesh/assets/docs/lunr-index-1760121512891.json +0 -1
- solace_agent_mesh/assets/docs/search-doc-1760121512891.json +0 -1
- solace_agent_mesh/client/webui/frontend/static/assets/main-2nd1gbaH.js +0 -339
- solace_agent_mesh/client/webui/frontend/static/assets/main-DoKXctCM.css +0 -1
- solace_agent_mesh/config_portal/frontend/static/client/assets/_index-BNuqpWDc.js +0 -98
- solace_agent_mesh/evaluation/config_loader.py +0 -657
- solace_agent_mesh/evaluation/test_case_loader.py +0 -714
- /solace_agent_mesh/assets/docs/assets/js/{main.bd3c34f3.js.LICENSE.txt → main.b12eac43.js.LICENSE.txt} +0 -0
- {solace_agent_mesh-1.5.1.dist-info → solace_agent_mesh-1.6.1.dist-info}/WHEEL +0 -0
- {solace_agent_mesh-1.5.1.dist-info → solace_agent_mesh-1.6.1.dist-info}/entry_points.txt +0 -0
- {solace_agent_mesh-1.5.1.dist-info → solace_agent_mesh-1.6.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -4,8 +4,10 @@ Repository interfaces defining contracts for data access.
|
|
|
4
4
|
|
|
5
5
|
from abc import ABC, abstractmethod
|
|
6
6
|
from typing import TYPE_CHECKING, Optional
|
|
7
|
+
from sqlalchemy.orm import Session as DBSession
|
|
7
8
|
|
|
8
|
-
from ..shared.
|
|
9
|
+
from ..shared.pagination import PaginationParams
|
|
10
|
+
from ..shared.types import SessionId, UserId
|
|
9
11
|
from .entities import Feedback, Session, Task, TaskEvent
|
|
10
12
|
|
|
11
13
|
if TYPE_CHECKING:
|
|
@@ -14,33 +16,33 @@ if TYPE_CHECKING:
|
|
|
14
16
|
|
|
15
17
|
class ISessionRepository(ABC):
|
|
16
18
|
"""Interface for session data access operations."""
|
|
17
|
-
|
|
19
|
+
|
|
18
20
|
@abstractmethod
|
|
19
21
|
def find_by_user(
|
|
20
|
-
self, user_id: UserId, pagination: PaginationParams | None = None
|
|
22
|
+
self, session: DBSession, user_id: UserId, pagination: PaginationParams | None = None
|
|
21
23
|
) -> list[Session]:
|
|
22
24
|
"""Find all sessions for a specific user."""
|
|
23
25
|
pass
|
|
24
26
|
|
|
25
27
|
@abstractmethod
|
|
26
|
-
def count_by_user(self, user_id: UserId) -> int:
|
|
28
|
+
def count_by_user(self, session: DBSession, user_id: UserId) -> int:
|
|
27
29
|
"""Count total sessions for a specific user."""
|
|
28
30
|
pass
|
|
29
31
|
|
|
30
32
|
@abstractmethod
|
|
31
33
|
def find_user_session(
|
|
32
|
-
self, session_id: SessionId, user_id: UserId
|
|
34
|
+
self, session: DBSession, session_id: SessionId, user_id: UserId
|
|
33
35
|
) -> Session | None:
|
|
34
36
|
"""Find a specific session belonging to a user."""
|
|
35
37
|
pass
|
|
36
38
|
|
|
37
39
|
@abstractmethod
|
|
38
|
-
def save(self, session: Session) -> Session:
|
|
40
|
+
def save(self, session: DBSession, session_obj: Session) -> Session:
|
|
39
41
|
"""Save or update a session."""
|
|
40
42
|
pass
|
|
41
43
|
|
|
42
44
|
@abstractmethod
|
|
43
|
-
def delete(self, session_id: SessionId, user_id: UserId) -> bool:
|
|
45
|
+
def delete(self, session: DBSession, session_id: SessionId, user_id: UserId) -> bool:
|
|
44
46
|
"""Delete a session belonging to a user."""
|
|
45
47
|
pass
|
|
46
48
|
|
|
@@ -49,28 +51,31 @@ class ITaskRepository(ABC):
|
|
|
49
51
|
"""Interface for task data access operations."""
|
|
50
52
|
|
|
51
53
|
@abstractmethod
|
|
52
|
-
def save_task(self, task: Task) -> Task:
|
|
54
|
+
def save_task(self, session: DBSession, task: Task) -> Task:
|
|
53
55
|
"""Create or update a task."""
|
|
54
56
|
pass
|
|
55
57
|
|
|
56
58
|
@abstractmethod
|
|
57
|
-
def save_event(self, event: TaskEvent) -> TaskEvent:
|
|
59
|
+
def save_event(self, session: DBSession, event: TaskEvent) -> TaskEvent:
|
|
58
60
|
"""Save a task event."""
|
|
59
61
|
pass
|
|
60
62
|
|
|
61
63
|
@abstractmethod
|
|
62
|
-
def find_by_id(self, task_id: str) -> Task | None:
|
|
64
|
+
def find_by_id(self, session: DBSession, task_id: str) -> Task | None:
|
|
63
65
|
"""Find a task by its ID."""
|
|
64
66
|
pass
|
|
65
67
|
|
|
66
68
|
@abstractmethod
|
|
67
|
-
def find_by_id_with_events(
|
|
69
|
+
def find_by_id_with_events(
|
|
70
|
+
self, session: DBSession, task_id: str
|
|
71
|
+
) -> tuple[Task, list[TaskEvent]] | None:
|
|
68
72
|
"""Find a task with all its events."""
|
|
69
73
|
pass
|
|
70
74
|
|
|
71
75
|
@abstractmethod
|
|
72
76
|
def search(
|
|
73
77
|
self,
|
|
78
|
+
session: DBSession,
|
|
74
79
|
user_id: UserId,
|
|
75
80
|
start_date: int | None = None,
|
|
76
81
|
end_date: int | None = None,
|
|
@@ -81,7 +86,7 @@ class ITaskRepository(ABC):
|
|
|
81
86
|
pass
|
|
82
87
|
|
|
83
88
|
@abstractmethod
|
|
84
|
-
def delete_tasks_older_than(self, cutoff_time_ms: int, batch_size: int) -> int:
|
|
89
|
+
def delete_tasks_older_than(self, session: DBSession, cutoff_time_ms: int, batch_size: int) -> int:
|
|
85
90
|
"""Delete tasks older than cutoff time using batch deletion."""
|
|
86
91
|
pass
|
|
87
92
|
|
|
@@ -90,12 +95,12 @@ class IFeedbackRepository(ABC):
|
|
|
90
95
|
"""Interface for feedback data access operations."""
|
|
91
96
|
|
|
92
97
|
@abstractmethod
|
|
93
|
-
def save(self, feedback: Feedback) -> Feedback:
|
|
98
|
+
def save(self, session: DBSession, feedback: Feedback) -> Feedback:
|
|
94
99
|
"""Save feedback."""
|
|
95
100
|
pass
|
|
96
101
|
|
|
97
102
|
@abstractmethod
|
|
98
|
-
def delete_feedback_older_than(self, cutoff_time_ms: int, batch_size: int) -> int:
|
|
103
|
+
def delete_feedback_older_than(self, session: DBSession, cutoff_time_ms: int, batch_size: int) -> int:
|
|
99
104
|
"""Delete feedback older than cutoff time using batch deletion."""
|
|
100
105
|
pass
|
|
101
106
|
|
|
@@ -104,21 +109,23 @@ class IChatTaskRepository(ABC):
|
|
|
104
109
|
"""Interface for chat task data access operations."""
|
|
105
110
|
|
|
106
111
|
@abstractmethod
|
|
107
|
-
def save(self, task: "ChatTask") -> "ChatTask":
|
|
112
|
+
def save(self, session: DBSession, task: "ChatTask") -> "ChatTask":
|
|
108
113
|
"""Save or update a chat task (upsert)."""
|
|
109
114
|
pass
|
|
110
115
|
|
|
111
116
|
@abstractmethod
|
|
112
|
-
def find_by_session(
|
|
117
|
+
def find_by_session(
|
|
118
|
+
self, session: DBSession, session_id: SessionId, user_id: UserId
|
|
119
|
+
) -> list["ChatTask"]:
|
|
113
120
|
"""Find all tasks for a session."""
|
|
114
121
|
pass
|
|
115
122
|
|
|
116
123
|
@abstractmethod
|
|
117
|
-
def find_by_id(self, task_id: str, user_id: UserId) -> Optional["ChatTask"]:
|
|
124
|
+
def find_by_id(self, session: DBSession, task_id: str, user_id: UserId) -> Optional["ChatTask"]:
|
|
118
125
|
"""Find a specific task."""
|
|
119
126
|
pass
|
|
120
127
|
|
|
121
128
|
@abstractmethod
|
|
122
|
-
def delete_by_session(self, session_id: SessionId) -> bool:
|
|
129
|
+
def delete_by_session(self, session: DBSession, session_id: SessionId) -> bool:
|
|
123
130
|
"""Delete all tasks for a session."""
|
|
124
131
|
pass
|
|
@@ -6,22 +6,17 @@ from sqlalchemy.orm import Session as DBSession
|
|
|
6
6
|
|
|
7
7
|
from ..shared.base_repository import PaginatedRepository
|
|
8
8
|
from ..shared.pagination import PaginationParams
|
|
9
|
-
from ..shared.types import
|
|
9
|
+
from ..shared.types import SessionId, UserId
|
|
10
10
|
from .entities import Session
|
|
11
11
|
from .interfaces import ISessionRepository
|
|
12
|
-
from .models import
|
|
13
|
-
SessionModel,
|
|
14
|
-
CreateSessionModel,
|
|
15
|
-
UpdateSessionModel,
|
|
16
|
-
)
|
|
12
|
+
from .models import CreateSessionModel, SessionModel, UpdateSessionModel
|
|
17
13
|
|
|
18
14
|
|
|
19
15
|
class SessionRepository(PaginatedRepository[SessionModel, Session], ISessionRepository):
|
|
20
16
|
"""SQLAlchemy implementation of session repository using BaseRepository."""
|
|
21
17
|
|
|
22
|
-
def __init__(self
|
|
18
|
+
def __init__(self):
|
|
23
19
|
super().__init__(SessionModel, Session)
|
|
24
|
-
self.db = db
|
|
25
20
|
|
|
26
21
|
@property
|
|
27
22
|
def entity_name(self) -> str:
|
|
@@ -29,29 +24,30 @@ class SessionRepository(PaginatedRepository[SessionModel, Session], ISessionRepo
|
|
|
29
24
|
return "session"
|
|
30
25
|
|
|
31
26
|
def find_by_user(
|
|
32
|
-
self, user_id: UserId, pagination: PaginationParams | None = None
|
|
27
|
+
self, session: DBSession, user_id: UserId, pagination: PaginationParams | None = None
|
|
33
28
|
) -> list[Session]:
|
|
34
29
|
"""Find all sessions for a specific user."""
|
|
35
|
-
query =
|
|
30
|
+
query = session.query(SessionModel).filter(SessionModel.user_id == user_id)
|
|
36
31
|
query = query.order_by(SessionModel.updated_time.desc())
|
|
37
32
|
|
|
38
33
|
if pagination:
|
|
39
|
-
|
|
40
|
-
query = query.offset(offset).limit(pagination.page_size)
|
|
34
|
+
query = query.offset(pagination.offset).limit(pagination.page_size)
|
|
41
35
|
|
|
42
36
|
models = query.all()
|
|
43
37
|
return [Session.model_validate(model) for model in models]
|
|
44
38
|
|
|
45
|
-
def count_by_user(self, user_id: UserId) -> int:
|
|
39
|
+
def count_by_user(self, session: DBSession, user_id: UserId) -> int:
|
|
46
40
|
"""Count total sessions for a specific user."""
|
|
47
|
-
return
|
|
41
|
+
return (
|
|
42
|
+
session.query(SessionModel).filter(SessionModel.user_id == user_id).count()
|
|
43
|
+
)
|
|
48
44
|
|
|
49
45
|
def find_user_session(
|
|
50
|
-
self, session_id: SessionId, user_id: UserId
|
|
46
|
+
self, session: DBSession, session_id: SessionId, user_id: UserId
|
|
51
47
|
) -> Session | None:
|
|
52
48
|
"""Find a specific session belonging to a user."""
|
|
53
49
|
model = (
|
|
54
|
-
|
|
50
|
+
session.query(SessionModel)
|
|
55
51
|
.filter(
|
|
56
52
|
SessionModel.id == session_id,
|
|
57
53
|
SessionModel.user_id == user_id,
|
|
@@ -60,9 +56,11 @@ class SessionRepository(PaginatedRepository[SessionModel, Session], ISessionRepo
|
|
|
60
56
|
)
|
|
61
57
|
return Session.model_validate(model) if model else None
|
|
62
58
|
|
|
63
|
-
def save(self, session: Session) -> Session:
|
|
59
|
+
def save(self, db_session: DBSession, session: Session) -> Session:
|
|
64
60
|
"""Save or update a session."""
|
|
65
|
-
existing_model =
|
|
61
|
+
existing_model = (
|
|
62
|
+
db_session.query(SessionModel).filter(SessionModel.id == session.id).first()
|
|
63
|
+
)
|
|
66
64
|
|
|
67
65
|
if existing_model:
|
|
68
66
|
update_model = UpdateSessionModel(
|
|
@@ -70,7 +68,9 @@ class SessionRepository(PaginatedRepository[SessionModel, Session], ISessionRepo
|
|
|
70
68
|
agent_id=session.agent_id,
|
|
71
69
|
updated_time=session.updated_time,
|
|
72
70
|
)
|
|
73
|
-
return self.update(
|
|
71
|
+
return self.update(
|
|
72
|
+
db_session, session.id, update_model.model_dump(exclude_none=True)
|
|
73
|
+
)
|
|
74
74
|
else:
|
|
75
75
|
create_model = CreateSessionModel(
|
|
76
76
|
id=session.id,
|
|
@@ -80,19 +80,23 @@ class SessionRepository(PaginatedRepository[SessionModel, Session], ISessionRepo
|
|
|
80
80
|
created_time=session.created_time,
|
|
81
81
|
updated_time=session.updated_time,
|
|
82
82
|
)
|
|
83
|
-
return self.create(
|
|
83
|
+
return self.create(db_session, create_model.model_dump())
|
|
84
84
|
|
|
85
|
-
def delete(self, session_id: SessionId, user_id: UserId) -> bool:
|
|
85
|
+
def delete(self, db_session: DBSession, session_id: SessionId, user_id: UserId) -> bool:
|
|
86
86
|
"""Delete a session belonging to a user."""
|
|
87
87
|
# Check if session belongs to user first
|
|
88
|
-
session_model =
|
|
89
|
-
SessionModel
|
|
90
|
-
|
|
91
|
-
|
|
88
|
+
session_model = (
|
|
89
|
+
db_session.query(SessionModel)
|
|
90
|
+
.filter(
|
|
91
|
+
SessionModel.id == session_id,
|
|
92
|
+
SessionModel.user_id == user_id,
|
|
93
|
+
)
|
|
94
|
+
.first()
|
|
95
|
+
)
|
|
92
96
|
|
|
93
97
|
if not session_model:
|
|
94
98
|
return False
|
|
95
99
|
|
|
96
100
|
# Use BaseRepository delete method
|
|
97
|
-
super().delete(
|
|
101
|
+
super().delete(db_session, session_id)
|
|
98
102
|
return True
|
|
@@ -4,7 +4,8 @@ Task repository implementation using SQLAlchemy.
|
|
|
4
4
|
|
|
5
5
|
from sqlalchemy.orm import Session as DBSession
|
|
6
6
|
|
|
7
|
-
from ..shared.
|
|
7
|
+
from ..shared.pagination import PaginationParams
|
|
8
|
+
from ..shared.types import UserId
|
|
8
9
|
from .entities import Task, TaskEvent
|
|
9
10
|
from .interfaces import ITaskRepository
|
|
10
11
|
from .models import TaskEventModel, TaskModel
|
|
@@ -13,15 +14,11 @@ from .models import TaskEventModel, TaskModel
|
|
|
13
14
|
class TaskRepository(ITaskRepository):
|
|
14
15
|
"""SQLAlchemy implementation of task repository."""
|
|
15
16
|
|
|
16
|
-
def
|
|
17
|
-
self.db = db
|
|
18
|
-
|
|
19
|
-
def save_task(self, task: Task) -> Task:
|
|
17
|
+
def save_task(self, session: DBSession, task: Task) -> Task:
|
|
20
18
|
"""Create or update a task."""
|
|
21
|
-
model =
|
|
19
|
+
model = session.query(TaskModel).filter(TaskModel.id == task.id).first()
|
|
22
20
|
|
|
23
21
|
if model:
|
|
24
|
-
# Update existing
|
|
25
22
|
model.end_time = task.end_time
|
|
26
23
|
model.status = task.status
|
|
27
24
|
model.total_input_tokens = task.total_input_tokens
|
|
@@ -29,7 +26,6 @@ class TaskRepository(ITaskRepository):
|
|
|
29
26
|
model.total_cached_input_tokens = task.total_cached_input_tokens
|
|
30
27
|
model.token_usage_details = task.token_usage_details
|
|
31
28
|
else:
|
|
32
|
-
# Create new
|
|
33
29
|
model = TaskModel(
|
|
34
30
|
id=task.id,
|
|
35
31
|
user_id=task.user_id,
|
|
@@ -42,13 +38,13 @@ class TaskRepository(ITaskRepository):
|
|
|
42
38
|
total_cached_input_tokens=task.total_cached_input_tokens,
|
|
43
39
|
token_usage_details=task.token_usage_details,
|
|
44
40
|
)
|
|
45
|
-
|
|
41
|
+
session.add(model)
|
|
46
42
|
|
|
47
|
-
|
|
48
|
-
|
|
43
|
+
session.flush()
|
|
44
|
+
session.refresh(model)
|
|
49
45
|
return self._task_model_to_entity(model)
|
|
50
46
|
|
|
51
|
-
def save_event(self, event: TaskEvent) -> TaskEvent:
|
|
47
|
+
def save_event(self, session: DBSession, event: TaskEvent) -> TaskEvent:
|
|
52
48
|
"""Save a task event."""
|
|
53
49
|
model = TaskEventModel(
|
|
54
50
|
id=event.id,
|
|
@@ -59,26 +55,26 @@ class TaskRepository(ITaskRepository):
|
|
|
59
55
|
direction=event.direction,
|
|
60
56
|
payload=event.payload,
|
|
61
57
|
)
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
58
|
+
session.add(model)
|
|
59
|
+
session.flush()
|
|
60
|
+
session.refresh(model)
|
|
65
61
|
return self._event_model_to_entity(model)
|
|
66
62
|
|
|
67
|
-
def find_by_id(self, task_id: str) -> Task | None:
|
|
63
|
+
def find_by_id(self, session: DBSession, task_id: str) -> Task | None:
|
|
68
64
|
"""Find a task by its ID."""
|
|
69
|
-
model =
|
|
65
|
+
model = session.query(TaskModel).filter(TaskModel.id == task_id).first()
|
|
70
66
|
return self._task_model_to_entity(model) if model else None
|
|
71
67
|
|
|
72
68
|
def find_by_id_with_events(
|
|
73
|
-
self, task_id: str
|
|
69
|
+
self, session: DBSession, task_id: str
|
|
74
70
|
) -> tuple[Task, list[TaskEvent]] | None:
|
|
75
71
|
"""Find a task with all its events."""
|
|
76
|
-
task_model =
|
|
72
|
+
task_model = session.query(TaskModel).filter(TaskModel.id == task_id).first()
|
|
77
73
|
if not task_model:
|
|
78
74
|
return None
|
|
79
75
|
|
|
80
76
|
event_models = (
|
|
81
|
-
|
|
77
|
+
session.query(TaskEventModel)
|
|
82
78
|
.filter(TaskEventModel.task_id == task_id)
|
|
83
79
|
.order_by(TaskEventModel.created_time.asc())
|
|
84
80
|
.all()
|
|
@@ -90,36 +86,31 @@ class TaskRepository(ITaskRepository):
|
|
|
90
86
|
|
|
91
87
|
def search(
|
|
92
88
|
self,
|
|
89
|
+
session: DBSession,
|
|
93
90
|
user_id: UserId,
|
|
94
91
|
start_date: int | None = None,
|
|
95
92
|
end_date: int | None = None,
|
|
96
|
-
search_query: str | None = None,
|
|
97
93
|
pagination: PaginationParams | None = None,
|
|
98
94
|
) -> list[Task]:
|
|
99
95
|
"""Search for tasks with filters."""
|
|
100
|
-
query =
|
|
101
|
-
if user_id != "*":
|
|
96
|
+
query = session.query(TaskModel)
|
|
97
|
+
if user_id != "*":
|
|
102
98
|
query = query.filter(TaskModel.user_id == user_id)
|
|
103
99
|
|
|
104
100
|
if start_date:
|
|
105
101
|
query = query.filter(TaskModel.start_time >= start_date)
|
|
106
102
|
if end_date:
|
|
107
103
|
query = query.filter(TaskModel.start_time <= end_date)
|
|
108
|
-
if search_query:
|
|
109
|
-
query = query.filter(
|
|
110
|
-
TaskModel.initial_request_text.ilike(f"%{search_query}%")
|
|
111
|
-
)
|
|
112
104
|
|
|
113
105
|
query = query.order_by(TaskModel.start_time.desc())
|
|
114
106
|
|
|
115
107
|
if pagination:
|
|
116
|
-
|
|
117
|
-
query = query.offset(offset).limit(pagination.page_size)
|
|
108
|
+
query = query.offset(pagination.offset).limit(pagination.page_size)
|
|
118
109
|
|
|
119
110
|
models = query.all()
|
|
120
111
|
return [self._task_model_to_entity(model) for model in models]
|
|
121
112
|
|
|
122
|
-
def delete_tasks_older_than(self, cutoff_time_ms: int, batch_size: int) -> int:
|
|
113
|
+
def delete_tasks_older_than(self, session: DBSession, cutoff_time_ms: int, batch_size: int) -> int:
|
|
123
114
|
"""
|
|
124
115
|
Delete tasks (and their events via cascade) older than the cutoff time.
|
|
125
116
|
Uses batch deletion to avoid long-running transactions.
|
|
@@ -130,38 +121,38 @@ class TaskRepository(ITaskRepository):
|
|
|
130
121
|
|
|
131
122
|
Returns:
|
|
132
123
|
Total number of tasks deleted
|
|
124
|
+
|
|
125
|
+
Note:
|
|
126
|
+
This method commits each batch internally due to the nature of batch processing.
|
|
127
|
+
Each batch is an atomic operation to prevent long-running transactions.
|
|
133
128
|
"""
|
|
134
129
|
total_deleted = 0
|
|
135
|
-
|
|
130
|
+
|
|
136
131
|
while True:
|
|
137
|
-
# Find a batch of task IDs to delete
|
|
138
132
|
task_ids_to_delete = (
|
|
139
|
-
|
|
133
|
+
session.query(TaskModel.id)
|
|
140
134
|
.filter(TaskModel.start_time < cutoff_time_ms)
|
|
141
135
|
.limit(batch_size)
|
|
142
136
|
.all()
|
|
143
137
|
)
|
|
144
|
-
|
|
138
|
+
|
|
145
139
|
if not task_ids_to_delete:
|
|
146
140
|
break
|
|
147
|
-
|
|
148
|
-
# Extract IDs from the result tuples
|
|
141
|
+
|
|
149
142
|
ids = [task_id[0] for task_id in task_ids_to_delete]
|
|
150
|
-
|
|
151
|
-
# Delete this batch
|
|
143
|
+
|
|
152
144
|
deleted_count = (
|
|
153
|
-
|
|
145
|
+
session.query(TaskModel)
|
|
154
146
|
.filter(TaskModel.id.in_(ids))
|
|
155
147
|
.delete(synchronize_session=False)
|
|
156
148
|
)
|
|
157
|
-
|
|
158
|
-
|
|
149
|
+
|
|
150
|
+
session.commit()
|
|
159
151
|
total_deleted += deleted_count
|
|
160
|
-
|
|
161
|
-
# If we deleted fewer than batch_size, we're done
|
|
152
|
+
|
|
162
153
|
if deleted_count < batch_size:
|
|
163
154
|
break
|
|
164
|
-
|
|
155
|
+
|
|
165
156
|
return total_deleted
|
|
166
157
|
|
|
167
158
|
def _task_model_to_entity(self, model: TaskModel) -> Task:
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
"""
|
|
2
|
-
API Router for agent discovery.
|
|
2
|
+
API Router for agent discovery and management.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
5
|
import logging
|
|
6
6
|
from fastapi import APIRouter, Depends, HTTPException, status
|
|
7
|
-
from typing import List
|
|
7
|
+
from typing import Dict, List
|
|
8
8
|
|
|
9
9
|
from ....common.agent_registry import AgentRegistry
|
|
10
10
|
from a2a.types import AgentCard
|
|
11
|
-
from ..dependencies import get_agent_registry
|
|
11
|
+
from ..dependencies import get_agent_registry, get_sac_component
|
|
12
|
+
from ..component import WebUIBackendComponent
|
|
12
13
|
|
|
13
14
|
log = logging.getLogger(__name__)
|
|
14
15
|
|