solace-agent-mesh 1.0.9__py3-none-any.whl → 1.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of solace-agent-mesh might be problematic. Click here for more details.
- solace_agent_mesh/agent/adk/adk_llm.txt +182 -42
- solace_agent_mesh/agent/adk/artifacts/artifacts_llm.txt +171 -0
- solace_agent_mesh/agent/adk/callbacks.py +165 -104
- solace_agent_mesh/agent/adk/embed_resolving_mcp_toolset.py +0 -18
- solace_agent_mesh/agent/adk/models/models_llm.txt +104 -55
- solace_agent_mesh/agent/adk/runner.py +25 -17
- solace_agent_mesh/agent/adk/services.py +3 -3
- solace_agent_mesh/agent/adk/setup.py +11 -0
- solace_agent_mesh/agent/adk/stream_parser.py +8 -1
- solace_agent_mesh/agent/adk/tool_wrapper.py +10 -3
- solace_agent_mesh/agent/agent_llm.txt +355 -18
- solace_agent_mesh/agent/protocol/event_handlers.py +460 -317
- solace_agent_mesh/agent/protocol/protocol_llm.txt +54 -7
- solace_agent_mesh/agent/sac/app.py +2 -2
- solace_agent_mesh/agent/sac/component.py +211 -517
- solace_agent_mesh/agent/sac/sac_llm.txt +133 -63
- solace_agent_mesh/agent/testing/testing_llm.txt +25 -58
- solace_agent_mesh/agent/tools/peer_agent_tool.py +15 -11
- solace_agent_mesh/agent/tools/tools_llm.txt +234 -69
- solace_agent_mesh/agent/utils/artifact_helpers.py +35 -1
- solace_agent_mesh/agent/utils/utils_llm.txt +90 -105
- solace_agent_mesh/assets/docs/404.html +3 -3
- solace_agent_mesh/assets/docs/assets/js/6e0db977.39a79ca9.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/{75384d09.ccd480c4.js → 75384d09.bf78fbdb.js} +1 -1
- solace_agent_mesh/assets/docs/assets/js/90dd9cf6.88f385ea.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/f284c35a.fb68323a.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/main.08d30374.js +2 -0
- solace_agent_mesh/assets/docs/assets/js/runtime~main.458efb1d.js +1 -0
- solace_agent_mesh/assets/docs/docs/documentation/concepts/agents/index.html +4 -4
- 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/migration-guides/a2a-upgrade-to-0.3.0/a2a-gateway-upgrade-to-0.3.0/index.html +105 -0
- solace_agent_mesh/assets/docs/docs/documentation/migration-guides/a2a-upgrade-to-0.3.0/a2a-technical-migration-map/index.html +53 -0
- 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 +4 -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-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-1757433031159.json +1 -0
- solace_agent_mesh/assets/docs/lunr-index.json +1 -1
- solace_agent_mesh/assets/docs/search-doc-1757433031159.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-vY5eu2lI.js +1 -0
- solace_agent_mesh/client/webui/frontend/static/assets/client-BeBkzgWW.js +25 -0
- solace_agent_mesh/client/webui/frontend/static/assets/main-Bjys1KQs.js +339 -0
- solace_agent_mesh/client/webui/frontend/static/assets/main-C03yrETa.css +1 -0
- solace_agent_mesh/client/webui/frontend/static/assets/vendor-CE0AeXyK.js +395 -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/a2a/__init__.py +213 -0
- solace_agent_mesh/common/a2a/a2a_llm.txt +182 -0
- solace_agent_mesh/common/a2a/artifact.py +328 -0
- solace_agent_mesh/common/a2a/events.py +183 -0
- solace_agent_mesh/common/a2a/message.py +307 -0
- solace_agent_mesh/common/a2a/protocol.py +513 -0
- solace_agent_mesh/common/a2a/task.py +127 -0
- solace_agent_mesh/common/a2a/translation.py +653 -0
- solace_agent_mesh/common/a2a/types.py +54 -0
- solace_agent_mesh/common/a2a_spec/a2a.json +2576 -0
- solace_agent_mesh/common/a2a_spec/a2a_spec_llm.txt +407 -0
- solace_agent_mesh/common/a2a_spec/schemas/agent_progress_update.json +18 -0
- solace_agent_mesh/common/a2a_spec/schemas/artifact_creation_progress.json +31 -0
- solace_agent_mesh/common/a2a_spec/schemas/llm_invocation.json +18 -0
- solace_agent_mesh/common/a2a_spec/schemas/schemas_llm.txt +235 -0
- solace_agent_mesh/common/a2a_spec/schemas/tool_invocation_start.json +26 -0
- solace_agent_mesh/common/a2a_spec/schemas/tool_result.json +25 -0
- solace_agent_mesh/common/agent_registry.py +1 -1
- solace_agent_mesh/common/common_llm.txt +192 -70
- solace_agent_mesh/common/data_parts.py +99 -0
- solace_agent_mesh/common/middleware/middleware_llm.txt +17 -17
- solace_agent_mesh/common/sac/__init__.py +0 -0
- solace_agent_mesh/common/sac/sac_llm.txt +71 -0
- solace_agent_mesh/common/sac/sam_component_base.py +252 -0
- solace_agent_mesh/common/services/providers/providers_llm.txt +51 -84
- solace_agent_mesh/common/services/services_llm.txt +206 -26
- solace_agent_mesh/common/utils/artifact_utils.py +29 -0
- solace_agent_mesh/common/utils/embeds/embeds_llm.txt +176 -80
- solace_agent_mesh/common/utils/embeds/resolver.py +1 -0
- solace_agent_mesh/common/utils/utils_llm.txt +323 -42
- solace_agent_mesh/config_portal/backend/common.py +2 -2
- solace_agent_mesh/config_portal/backend/plugin_catalog/constants.py +1 -1
- 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/core_a2a/core_a2a_llm.txt +10 -8
- solace_agent_mesh/core_a2a/service.py +20 -44
- 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/base/app.py +27 -1
- solace_agent_mesh/gateway/base/base_llm.txt +177 -72
- solace_agent_mesh/gateway/base/component.py +294 -523
- solace_agent_mesh/gateway/gateway_llm.txt +299 -58
- 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 +371 -236
- solace_agent_mesh/gateway/http_sse/components/components_llm.txt +29 -29
- solace_agent_mesh/gateway/http_sse/dependencies.py +142 -39
- 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/http_sse_llm.txt +272 -36
- 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 +293 -91
- solace_agent_mesh/gateway/http_sse/routers/agents.py +1 -1
- solace_agent_mesh/gateway/http_sse/routers/artifacts.py +137 -56
- solace_agent_mesh/gateway/http_sse/routers/config.py +3 -1
- solace_agent_mesh/gateway/http_sse/routers/routers_llm.txt +231 -5
- solace_agent_mesh/gateway/http_sse/routers/tasks.py +199 -171
- solace_agent_mesh/gateway/http_sse/routers/visualization.py +7 -7
- solace_agent_mesh/gateway/http_sse/services/agent_service.py +1 -1
- solace_agent_mesh/gateway/http_sse/services/services_llm.txt +89 -135
- solace_agent_mesh/gateway/http_sse/services/task_service.py +2 -5
- 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/solace_agent_mesh_llm.txt +362 -0
- solace_agent_mesh/templates/gateway_component_template.py +149 -98
- solace_agent_mesh/templates/shared_config.yaml +4 -5
- solace_agent_mesh/templates/webui.yaml +8 -10
- {solace_agent_mesh-1.0.9.dist-info → solace_agent_mesh-1.3.0.dist-info}/METADATA +9 -6
- {solace_agent_mesh-1.0.9.dist-info → solace_agent_mesh-1.3.0.dist-info}/RECORD +197 -141
- solace_agent_mesh/assets/docs/assets/js/f284c35a.731836ad.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/main.3d0e7879.js +0 -2
- solace_agent_mesh/assets/docs/assets/js/runtime~main.05d19492.js +0 -1
- solace_agent_mesh/assets/docs/lunr-index-1757091012487.json +0 -1
- solace_agent_mesh/assets/docs/search-doc-1757091012487.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-D0FnP_W4.css +0 -1
- solace_agent_mesh/client/webui/frontend/static/assets/main-Do32sFPX.js +0 -708
- solace_agent_mesh/common/a2a_protocol.py +0 -564
- solace_agent_mesh/common/client/__init__.py +0 -4
- solace_agent_mesh/common/client/card_resolver.py +0 -21
- solace_agent_mesh/common/client/client.py +0 -85
- solace_agent_mesh/common/client/client_llm.txt +0 -133
- solace_agent_mesh/common/server/__init__.py +0 -4
- solace_agent_mesh/common/server/server.py +0 -122
- solace_agent_mesh/common/server/server_llm.txt +0 -169
- solace_agent_mesh/common/server/task_manager.py +0 -291
- solace_agent_mesh/common/server/utils.py +0 -28
- solace_agent_mesh/common/types.py +0 -411
- solace_agent_mesh/config_portal/frontend/static/client/assets/_index-Bym6YkMd.js +0 -98
- solace_agent_mesh/gateway/http_sse/routers/sessions.py +0 -80
- solace_agent_mesh/gateway/http_sse/routers/users.py +0 -59
- /solace_agent_mesh/assets/docs/assets/js/{main.3d0e7879.js.LICENSE.txt → main.08d30374.js.LICENSE.txt} +0 -0
- {solace_agent_mesh-1.0.9.dist-info → solace_agent_mesh-1.3.0.dist-info}/WHEEL +0 -0
- {solace_agent_mesh-1.0.9.dist-info → solace_agent_mesh-1.3.0.dist-info}/entry_points.txt +0 -0
- {solace_agent_mesh-1.0.9.dist-info → solace_agent_mesh-1.3.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
from fastapi import APIRouter, Body, Depends, HTTPException, status
|
|
2
|
+
from solace_ai_connector.common.log import log
|
|
3
|
+
|
|
4
|
+
from ...application.services.session_service import SessionService
|
|
5
|
+
from ...dependencies import (
|
|
6
|
+
PublishFunc,
|
|
7
|
+
get_namespace,
|
|
8
|
+
get_publish_a2a_func,
|
|
9
|
+
get_session_service,
|
|
10
|
+
)
|
|
11
|
+
from ...shared.auth_utils import get_current_user
|
|
12
|
+
from ..dto.requests.session_requests import (
|
|
13
|
+
DeleteSessionRequest,
|
|
14
|
+
GetSessionHistoryRequest,
|
|
15
|
+
GetSessionRequest,
|
|
16
|
+
GetSessionsRequest,
|
|
17
|
+
UpdateSessionRequest,
|
|
18
|
+
)
|
|
19
|
+
from ..dto.responses.session_responses import (
|
|
20
|
+
MessageResponse,
|
|
21
|
+
SessionListResponse,
|
|
22
|
+
SessionResponse,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
router = APIRouter()
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@router.get("/sessions", response_model=SessionListResponse)
|
|
29
|
+
async def get_all_sessions(
|
|
30
|
+
user: dict = Depends(get_current_user),
|
|
31
|
+
session_service: SessionService = Depends(get_session_service),
|
|
32
|
+
):
|
|
33
|
+
user_id = user.get("id")
|
|
34
|
+
log.info("Fetching sessions for user_id: %s", user_id)
|
|
35
|
+
|
|
36
|
+
try:
|
|
37
|
+
request_dto = GetSessionsRequest(user_id=user_id)
|
|
38
|
+
|
|
39
|
+
session_domains = session_service.get_user_sessions(
|
|
40
|
+
user_id=request_dto.user_id, pagination=request_dto.pagination
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
session_responses = []
|
|
44
|
+
for domain in session_domains:
|
|
45
|
+
session_response = SessionResponse(
|
|
46
|
+
id=domain.id,
|
|
47
|
+
user_id=domain.user_id,
|
|
48
|
+
name=domain.name,
|
|
49
|
+
agent_id=domain.agent_id,
|
|
50
|
+
status=domain.status,
|
|
51
|
+
created_at=domain.created_at,
|
|
52
|
+
updated_at=domain.updated_at,
|
|
53
|
+
last_activity=domain.last_activity,
|
|
54
|
+
)
|
|
55
|
+
session_responses.append(session_response)
|
|
56
|
+
|
|
57
|
+
return SessionListResponse(
|
|
58
|
+
sessions=session_responses,
|
|
59
|
+
total_count=len(session_responses),
|
|
60
|
+
pagination=request_dto.pagination,
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
except Exception as e:
|
|
64
|
+
log.error("Error fetching sessions for user %s: %s", user_id, e)
|
|
65
|
+
raise HTTPException(
|
|
66
|
+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
67
|
+
detail="Failed to retrieve sessions",
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@router.get("/sessions/{session_id}", response_model=SessionResponse)
|
|
72
|
+
async def get_session(
|
|
73
|
+
session_id: str,
|
|
74
|
+
user: dict = Depends(get_current_user),
|
|
75
|
+
session_service: SessionService = Depends(get_session_service),
|
|
76
|
+
):
|
|
77
|
+
user_id = user.get("id")
|
|
78
|
+
log.info("User %s attempting to fetch session_id: %s", user_id, session_id)
|
|
79
|
+
|
|
80
|
+
try:
|
|
81
|
+
if (
|
|
82
|
+
not session_id
|
|
83
|
+
or session_id.strip() == ""
|
|
84
|
+
or session_id in ["null", "undefined"]
|
|
85
|
+
):
|
|
86
|
+
raise HTTPException(
|
|
87
|
+
status_code=status.HTTP_404_NOT_FOUND, detail="Session not found."
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
request_dto = GetSessionRequest(session_id=session_id, user_id=user_id)
|
|
91
|
+
|
|
92
|
+
session_domain = session_service.get_session(
|
|
93
|
+
session_id=request_dto.session_id, user_id=request_dto.user_id
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
if not session_domain:
|
|
97
|
+
raise HTTPException(
|
|
98
|
+
status_code=status.HTTP_404_NOT_FOUND, detail="Session not found."
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
log.info("User %s authorized. Fetching session_id: %s", user_id, session_id)
|
|
102
|
+
|
|
103
|
+
return SessionResponse(
|
|
104
|
+
id=session_domain.id,
|
|
105
|
+
user_id=session_domain.user_id,
|
|
106
|
+
name=session_domain.name,
|
|
107
|
+
agent_id=session_domain.agent_id,
|
|
108
|
+
status=session_domain.status,
|
|
109
|
+
created_at=session_domain.created_at,
|
|
110
|
+
updated_at=session_domain.updated_at,
|
|
111
|
+
last_activity=session_domain.last_activity,
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
except HTTPException:
|
|
115
|
+
raise
|
|
116
|
+
except Exception as e:
|
|
117
|
+
log.error(
|
|
118
|
+
"Error fetching session %s for user %s: %s",
|
|
119
|
+
session_id,
|
|
120
|
+
user_id,
|
|
121
|
+
e,
|
|
122
|
+
)
|
|
123
|
+
raise HTTPException(
|
|
124
|
+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
125
|
+
detail="Failed to retrieve session",
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
@router.get("/sessions/{session_id}/messages")
|
|
130
|
+
async def get_session_history(
|
|
131
|
+
session_id: str,
|
|
132
|
+
user: dict = Depends(get_current_user),
|
|
133
|
+
session_service: SessionService = Depends(get_session_service),
|
|
134
|
+
):
|
|
135
|
+
user_id = user.get("id")
|
|
136
|
+
log.info(
|
|
137
|
+
"User %s attempting to fetch history for session_id: %s", user_id, session_id
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
try:
|
|
141
|
+
if (
|
|
142
|
+
not session_id
|
|
143
|
+
or session_id.strip() == ""
|
|
144
|
+
or session_id in ["null", "undefined"]
|
|
145
|
+
):
|
|
146
|
+
raise HTTPException(
|
|
147
|
+
status_code=status.HTTP_404_NOT_FOUND, detail="Session not found."
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
request_dto = GetSessionHistoryRequest(session_id=session_id, user_id=user_id)
|
|
151
|
+
|
|
152
|
+
history_domain = session_service.get_session_history(
|
|
153
|
+
session_id=request_dto.session_id,
|
|
154
|
+
user_id=request_dto.user_id,
|
|
155
|
+
pagination=request_dto.pagination,
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
if not history_domain:
|
|
159
|
+
raise HTTPException(
|
|
160
|
+
status_code=status.HTTP_404_NOT_FOUND, detail="Session not found."
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
log.info(
|
|
164
|
+
"User %s authorized. Fetching history for session_id: %s",
|
|
165
|
+
user_id,
|
|
166
|
+
session_id,
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
message_responses = []
|
|
170
|
+
for message_domain in history_domain.messages:
|
|
171
|
+
message_response = MessageResponse(
|
|
172
|
+
id=message_domain.id,
|
|
173
|
+
session_id=message_domain.session_id,
|
|
174
|
+
message=message_domain.message,
|
|
175
|
+
sender_type=message_domain.sender_type,
|
|
176
|
+
sender_name=message_domain.sender_name,
|
|
177
|
+
message_type=message_domain.message_type,
|
|
178
|
+
timestamp=message_domain.created_at,
|
|
179
|
+
created_at=message_domain.created_at,
|
|
180
|
+
)
|
|
181
|
+
message_responses.append(message_response)
|
|
182
|
+
|
|
183
|
+
return message_responses
|
|
184
|
+
|
|
185
|
+
except HTTPException:
|
|
186
|
+
raise
|
|
187
|
+
except Exception as e:
|
|
188
|
+
log.error(
|
|
189
|
+
"Error fetching history for session %s for user %s: %s",
|
|
190
|
+
session_id,
|
|
191
|
+
user_id,
|
|
192
|
+
e,
|
|
193
|
+
)
|
|
194
|
+
raise HTTPException(
|
|
195
|
+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
196
|
+
detail="Failed to retrieve session history",
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
@router.patch("/sessions/{session_id}", response_model=SessionResponse)
|
|
201
|
+
async def update_session_name(
|
|
202
|
+
session_id: str,
|
|
203
|
+
name: str = Body(..., embed=True),
|
|
204
|
+
user: dict = Depends(get_current_user),
|
|
205
|
+
session_service: SessionService = Depends(get_session_service),
|
|
206
|
+
):
|
|
207
|
+
user_id = user.get("id")
|
|
208
|
+
log.info("User %s attempting to update session %s", user_id, session_id)
|
|
209
|
+
|
|
210
|
+
try:
|
|
211
|
+
if (
|
|
212
|
+
not session_id
|
|
213
|
+
or session_id.strip() == ""
|
|
214
|
+
or session_id in ["null", "undefined"]
|
|
215
|
+
):
|
|
216
|
+
raise HTTPException(
|
|
217
|
+
status_code=status.HTTP_404_NOT_FOUND, detail="Session not found."
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
request_dto = UpdateSessionRequest(
|
|
221
|
+
session_id=session_id, user_id=user_id, name=name
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
updated_domain = session_service.update_session_name(
|
|
225
|
+
session_id=request_dto.session_id,
|
|
226
|
+
user_id=request_dto.user_id,
|
|
227
|
+
name=request_dto.name,
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
if not updated_domain:
|
|
231
|
+
raise HTTPException(
|
|
232
|
+
status_code=status.HTTP_404_NOT_FOUND, detail="Session not found."
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
log.info("Session %s updated successfully", session_id)
|
|
236
|
+
|
|
237
|
+
return SessionResponse(
|
|
238
|
+
id=updated_domain.id,
|
|
239
|
+
user_id=updated_domain.user_id,
|
|
240
|
+
name=updated_domain.name,
|
|
241
|
+
agent_id=updated_domain.agent_id,
|
|
242
|
+
status=updated_domain.status,
|
|
243
|
+
created_at=updated_domain.created_at,
|
|
244
|
+
updated_at=updated_domain.updated_at,
|
|
245
|
+
last_activity=updated_domain.last_activity,
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
except HTTPException:
|
|
249
|
+
raise
|
|
250
|
+
except ValueError as e:
|
|
251
|
+
log.warning("Validation error updating session %s: %s", session_id, e)
|
|
252
|
+
raise HTTPException(
|
|
253
|
+
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=str(e)
|
|
254
|
+
)
|
|
255
|
+
except Exception as e:
|
|
256
|
+
log.error(
|
|
257
|
+
"Error updating session %s for user %s: %s",
|
|
258
|
+
session_id,
|
|
259
|
+
user_id,
|
|
260
|
+
e,
|
|
261
|
+
)
|
|
262
|
+
raise HTTPException(
|
|
263
|
+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
264
|
+
detail="Failed to update session",
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
@router.delete("/sessions/{session_id}", status_code=status.HTTP_204_NO_CONTENT)
|
|
269
|
+
async def delete_session(
|
|
270
|
+
session_id: str,
|
|
271
|
+
user: dict = Depends(get_current_user),
|
|
272
|
+
session_service: SessionService = Depends(get_session_service),
|
|
273
|
+
publish_func: PublishFunc = Depends(get_publish_a2a_func),
|
|
274
|
+
namespace: str = Depends(get_namespace),
|
|
275
|
+
):
|
|
276
|
+
user_id = user.get("id")
|
|
277
|
+
log.info("User %s attempting to delete session %s", user_id, session_id)
|
|
278
|
+
|
|
279
|
+
try:
|
|
280
|
+
if (
|
|
281
|
+
not session_id
|
|
282
|
+
or session_id.strip() == ""
|
|
283
|
+
or session_id in ["null", "undefined"]
|
|
284
|
+
):
|
|
285
|
+
raise HTTPException(
|
|
286
|
+
status_code=status.HTTP_404_NOT_FOUND, detail="Session not found."
|
|
287
|
+
)
|
|
288
|
+
|
|
289
|
+
request_dto = DeleteSessionRequest(session_id=session_id, user_id=user_id)
|
|
290
|
+
|
|
291
|
+
# Get session details before deletion to find the agent_id
|
|
292
|
+
session = session_service.get_session(session_id=session_id, user_id=user_id)
|
|
293
|
+
if not session:
|
|
294
|
+
raise HTTPException(
|
|
295
|
+
status_code=status.HTTP_404_NOT_FOUND, detail="Session not found."
|
|
296
|
+
)
|
|
297
|
+
|
|
298
|
+
agent_id = session.agent_id
|
|
299
|
+
|
|
300
|
+
deleted = session_service.delete_session(
|
|
301
|
+
session_id=request_dto.session_id, user_id=request_dto.user_id
|
|
302
|
+
)
|
|
303
|
+
|
|
304
|
+
if not deleted:
|
|
305
|
+
raise HTTPException(
|
|
306
|
+
status_code=status.HTTP_404_NOT_FOUND, detail="Session not found."
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
log.info("Session %s deleted successfully", session_id)
|
|
310
|
+
|
|
311
|
+
if agent_id:
|
|
312
|
+
try:
|
|
313
|
+
from solace_agent_mesh.common.a2a.protocol import (
|
|
314
|
+
get_agent_request_topic,
|
|
315
|
+
)
|
|
316
|
+
|
|
317
|
+
control_message = {
|
|
318
|
+
"control": {
|
|
319
|
+
"action": "delete_session",
|
|
320
|
+
"session_id": session_id,
|
|
321
|
+
"user_id": user_id,
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
target_topic = get_agent_request_topic(namespace, agent_id)
|
|
326
|
+
|
|
327
|
+
log.info(
|
|
328
|
+
"Sending session deletion notification to agent %s for session %s",
|
|
329
|
+
agent_id,
|
|
330
|
+
session_id,
|
|
331
|
+
)
|
|
332
|
+
|
|
333
|
+
publish_func(target_topic, control_message, None)
|
|
334
|
+
|
|
335
|
+
except Exception as e:
|
|
336
|
+
log.warning(
|
|
337
|
+
"Failed to notify agent %s about session %s deletion: %s",
|
|
338
|
+
agent_id,
|
|
339
|
+
session_id,
|
|
340
|
+
e,
|
|
341
|
+
)
|
|
342
|
+
|
|
343
|
+
except HTTPException:
|
|
344
|
+
raise
|
|
345
|
+
except Exception as e:
|
|
346
|
+
log.error(
|
|
347
|
+
"Error deleting session %s for user %s: %s",
|
|
348
|
+
session_id,
|
|
349
|
+
user_id,
|
|
350
|
+
e,
|
|
351
|
+
)
|
|
352
|
+
raise HTTPException(
|
|
353
|
+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
354
|
+
detail="Failed to delete session",
|
|
355
|
+
)
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING
|
|
2
|
+
|
|
3
|
+
from fastapi import APIRouter, Depends, File, Form, HTTPException
|
|
4
|
+
from fastapi import Request as FastAPIRequest
|
|
5
|
+
from fastapi import UploadFile, status
|
|
6
|
+
from solace_ai_connector.common.log import log
|
|
7
|
+
|
|
8
|
+
from a2a.types import InternalError, InvalidRequestError, JSONRPCResponse
|
|
9
|
+
from .....common import a2a
|
|
10
|
+
from ...dependencies import (
|
|
11
|
+
get_sac_component,
|
|
12
|
+
get_session_manager,
|
|
13
|
+
get_user_id,
|
|
14
|
+
)
|
|
15
|
+
from ...session_manager import SessionManager
|
|
16
|
+
from ...shared.enums import SenderType
|
|
17
|
+
from ..dto.requests.task_requests import (
|
|
18
|
+
CancelTaskRequest,
|
|
19
|
+
ProcessedTaskRequest,
|
|
20
|
+
TaskFilesInfo,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
if TYPE_CHECKING:
|
|
24
|
+
from ...component import WebUIBackendComponent
|
|
25
|
+
|
|
26
|
+
router = APIRouter()
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@router.post("/send", response_model=JSONRPCResponse)
|
|
30
|
+
async def send_task_to_agent(
|
|
31
|
+
request: FastAPIRequest,
|
|
32
|
+
agent_name: str = Form(...),
|
|
33
|
+
message: str = Form(...),
|
|
34
|
+
files: list[UploadFile] = File([]),
|
|
35
|
+
session_manager: SessionManager = Depends(get_session_manager),
|
|
36
|
+
component: "WebUIBackendComponent" = Depends(get_sac_component),
|
|
37
|
+
user_id: str = Depends(get_user_id),
|
|
38
|
+
):
|
|
39
|
+
"""
|
|
40
|
+
Submits a non-streaming task request to the specified agent.
|
|
41
|
+
This corresponds to the A2A `tasks/send` method.
|
|
42
|
+
"""
|
|
43
|
+
log_prefix = "[POST /api/v1/tasks/send] "
|
|
44
|
+
log.info("%sReceived request for agent: %s", log_prefix, agent_name)
|
|
45
|
+
|
|
46
|
+
try:
|
|
47
|
+
task_files = []
|
|
48
|
+
for file in files:
|
|
49
|
+
if file.filename:
|
|
50
|
+
task_files.append(
|
|
51
|
+
TaskFilesInfo(
|
|
52
|
+
filename=file.filename,
|
|
53
|
+
content_type=file.content_type or "application/octet-stream",
|
|
54
|
+
size=0, # We'd need to read the file to get size
|
|
55
|
+
)
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
request_dto = ProcessedTaskRequest(
|
|
59
|
+
agent_name=agent_name, message=message, user_id=user_id, files=task_files
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
# Continue with existing logic
|
|
63
|
+
client_id = session_manager.get_a2a_client_id(request)
|
|
64
|
+
session_id = session_manager.ensure_a2a_session(request)
|
|
65
|
+
|
|
66
|
+
log.info(
|
|
67
|
+
"%sUsing ClientID: %s, SessionID: %s", log_prefix, client_id, session_id
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
external_event_data = {
|
|
71
|
+
"agent_name": agent_name,
|
|
72
|
+
"message": message,
|
|
73
|
+
"files": files,
|
|
74
|
+
"client_id": client_id,
|
|
75
|
+
"a2a_session_id": session_id,
|
|
76
|
+
}
|
|
77
|
+
(
|
|
78
|
+
target_agent,
|
|
79
|
+
a2a_parts,
|
|
80
|
+
external_request_context,
|
|
81
|
+
) = await component._translate_external_input(external_event_data)
|
|
82
|
+
|
|
83
|
+
user_identity = {"id": user_id}
|
|
84
|
+
log.info(
|
|
85
|
+
"%sAuthenticated user identity: %s",
|
|
86
|
+
log_prefix,
|
|
87
|
+
user_identity.get("id", "unknown"),
|
|
88
|
+
)
|
|
89
|
+
task_id = await component.submit_a2a_task(
|
|
90
|
+
target_agent_name=target_agent,
|
|
91
|
+
a2a_parts=a2a_parts,
|
|
92
|
+
user_identity=user_identity,
|
|
93
|
+
external_request_context=external_request_context,
|
|
94
|
+
is_streaming=False,
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
log.info(
|
|
98
|
+
"%sNon-streaming task submitted successfully. TaskID: %s",
|
|
99
|
+
log_prefix,
|
|
100
|
+
task_id,
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
return JSONRPCResponse(result={"taskId": task_id})
|
|
104
|
+
|
|
105
|
+
except InvalidRequestError as e:
|
|
106
|
+
log.warning("%sInvalid request: %s", log_prefix, e.message, exc_info=True)
|
|
107
|
+
raise HTTPException(
|
|
108
|
+
status_code=status.HTTP_400_BAD_REQUEST,
|
|
109
|
+
detail=e.model_dump(exclude_none=True),
|
|
110
|
+
)
|
|
111
|
+
except Exception as e:
|
|
112
|
+
log.exception("%sUnexpected error processing task: %s", log_prefix, e)
|
|
113
|
+
error_resp = a2a.create_internal_error(message=f"Failed to process task: {e}")
|
|
114
|
+
raise HTTPException(
|
|
115
|
+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
116
|
+
detail=error_resp.model_dump(exclude_none=True),
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
@router.post("/subscribe", response_model=JSONRPCResponse)
|
|
121
|
+
async def subscribe_task_from_agent(
|
|
122
|
+
request: FastAPIRequest,
|
|
123
|
+
agent_name: str = Form(...),
|
|
124
|
+
message: str = Form(...),
|
|
125
|
+
files: list[UploadFile] = File([]),
|
|
126
|
+
session_id: str | None = Form(None),
|
|
127
|
+
session_manager: SessionManager = Depends(get_session_manager),
|
|
128
|
+
component: "WebUIBackendComponent" = Depends(get_sac_component),
|
|
129
|
+
user_id: str = Depends(get_user_id),
|
|
130
|
+
):
|
|
131
|
+
"""
|
|
132
|
+
Submits a streaming task request (`tasks/sendSubscribe`) to the specified agent.
|
|
133
|
+
"""
|
|
134
|
+
log_prefix = "[POST /api/v1/tasks/subscribe] "
|
|
135
|
+
log.info("%sReceived streaming request for agent: %s", log_prefix, agent_name)
|
|
136
|
+
|
|
137
|
+
try:
|
|
138
|
+
task_files = []
|
|
139
|
+
for file in files:
|
|
140
|
+
if file.filename:
|
|
141
|
+
task_files.append(
|
|
142
|
+
TaskFilesInfo(
|
|
143
|
+
filename=file.filename,
|
|
144
|
+
content_type=file.content_type or "application/octet-stream",
|
|
145
|
+
size=0,
|
|
146
|
+
)
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
request_dto = ProcessedTaskRequest(
|
|
150
|
+
agent_name=agent_name,
|
|
151
|
+
message=message,
|
|
152
|
+
user_id=user_id,
|
|
153
|
+
session_id=session_id,
|
|
154
|
+
files=task_files,
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
client_id = session_manager.get_a2a_client_id(request)
|
|
158
|
+
|
|
159
|
+
# If session_id is not provided by the client, create a new one.
|
|
160
|
+
if not session_id:
|
|
161
|
+
log.info("%sNo session_id provided, creating a new one.", log_prefix)
|
|
162
|
+
session_id = session_manager.start_new_a2a_session(request)
|
|
163
|
+
|
|
164
|
+
# Store message only if persistence is available
|
|
165
|
+
if hasattr(component, "persistence_service") and component.persistence_service:
|
|
166
|
+
try:
|
|
167
|
+
from ...dependencies import get_session_service
|
|
168
|
+
session_service = get_session_service(component)
|
|
169
|
+
message_domain = session_service.add_message_to_session(
|
|
170
|
+
session_id=session_id,
|
|
171
|
+
user_id=user_id,
|
|
172
|
+
message=message,
|
|
173
|
+
sender_type=SenderType.USER,
|
|
174
|
+
sender_name=user_id,
|
|
175
|
+
agent_id=agent_name,
|
|
176
|
+
)
|
|
177
|
+
# Use the actual session ID from the message (may be different if session was recreated)
|
|
178
|
+
if message_domain:
|
|
179
|
+
session_id = message_domain.session_id
|
|
180
|
+
except ValueError as e:
|
|
181
|
+
# Handle business domain validation errors
|
|
182
|
+
log.warning("Validation error in session service: %s", e)
|
|
183
|
+
raise HTTPException(
|
|
184
|
+
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=str(e)
|
|
185
|
+
)
|
|
186
|
+
except Exception as e:
|
|
187
|
+
log.error("Failed to store message in session service: %s", e)
|
|
188
|
+
raise HTTPException(
|
|
189
|
+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
190
|
+
detail="Failed to store message",
|
|
191
|
+
)
|
|
192
|
+
else:
|
|
193
|
+
log.debug("%sNo persistence available - skipping message storage", log_prefix)
|
|
194
|
+
|
|
195
|
+
log.info(
|
|
196
|
+
"%sUsing ClientID: %s, SessionID: %s", log_prefix, client_id, session_id
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
external_event_data = {
|
|
200
|
+
"agent_name": agent_name,
|
|
201
|
+
"message": message,
|
|
202
|
+
"files": files,
|
|
203
|
+
"client_id": client_id,
|
|
204
|
+
"a2a_session_id": session_id,
|
|
205
|
+
}
|
|
206
|
+
(
|
|
207
|
+
target_agent,
|
|
208
|
+
a2a_parts,
|
|
209
|
+
external_request_context,
|
|
210
|
+
) = await component._translate_external_input(external_event_data)
|
|
211
|
+
|
|
212
|
+
user_identity = {"id": user_id}
|
|
213
|
+
log.info(
|
|
214
|
+
"%sAuthenticated user identity: %s",
|
|
215
|
+
log_prefix,
|
|
216
|
+
user_identity.get("id", "unknown"),
|
|
217
|
+
)
|
|
218
|
+
task_id = await component.submit_a2a_task(
|
|
219
|
+
target_agent_name=target_agent,
|
|
220
|
+
a2a_parts=a2a_parts,
|
|
221
|
+
user_identity=user_identity,
|
|
222
|
+
external_request_context=external_request_context,
|
|
223
|
+
is_streaming=True,
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
log.info(
|
|
227
|
+
"%sStreaming task submitted successfully. TaskID: %s", log_prefix, task_id
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
return JSONRPCResponse(result={"taskId": task_id, "sessionId": session_id})
|
|
231
|
+
|
|
232
|
+
except InvalidRequestError as e:
|
|
233
|
+
log.warning("%sInvalid request: %s", log_prefix, e.message, exc_info=True)
|
|
234
|
+
raise HTTPException(
|
|
235
|
+
status_code=status.HTTP_400_BAD_REQUEST,
|
|
236
|
+
detail=e.model_dump(exclude_none=True),
|
|
237
|
+
)
|
|
238
|
+
except HTTPException:
|
|
239
|
+
# Re-raise HTTPExceptions (like 422 validation errors) without modification
|
|
240
|
+
raise
|
|
241
|
+
except Exception as e:
|
|
242
|
+
log.exception("%sUnexpected error processing task: %s", log_prefix, e)
|
|
243
|
+
error_resp = a2a.create_internal_error(message=f"Failed to process task: {e}")
|
|
244
|
+
raise HTTPException(
|
|
245
|
+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
246
|
+
detail=error_resp.model_dump(exclude_none=True),
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
@router.post("/cancel", response_model=JSONRPCResponse)
|
|
251
|
+
async def cancel_agent_task(
|
|
252
|
+
request: FastAPIRequest,
|
|
253
|
+
task_id: str = Form(...),
|
|
254
|
+
session_manager: SessionManager = Depends(get_session_manager),
|
|
255
|
+
component: "WebUIBackendComponent" = Depends(get_sac_component),
|
|
256
|
+
user_id: str = Depends(get_user_id),
|
|
257
|
+
):
|
|
258
|
+
"""
|
|
259
|
+
Sends a cancellation request for a specific task.
|
|
260
|
+
"""
|
|
261
|
+
log_prefix = f"[POST /api/v1/tasks/cancel] TaskID: {task_id} "
|
|
262
|
+
log.info("%sReceived cancellation request.", log_prefix)
|
|
263
|
+
|
|
264
|
+
try:
|
|
265
|
+
request_dto = CancelTaskRequest(task_id=task_id, user_id=user_id)
|
|
266
|
+
|
|
267
|
+
client_id = session_manager.get_a2a_client_id(request)
|
|
268
|
+
await component.cancel_a2a_task(task_id, client_id)
|
|
269
|
+
log.info("%sCancellation request sent successfully.", log_prefix)
|
|
270
|
+
return JSONRPCResponse(
|
|
271
|
+
result={"message": f"Cancellation request sent for task {task_id}"}
|
|
272
|
+
)
|
|
273
|
+
except Exception as e:
|
|
274
|
+
log.exception("%sUnexpected error sending cancellation: %s", log_prefix, e)
|
|
275
|
+
error_resp = a2a.create_internal_error(message="Unexpected server error: %s" % e)
|
|
276
|
+
raise HTTPException(
|
|
277
|
+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
278
|
+
detail=error_resp.model_dump(exclude_none=True),
|
|
279
|
+
)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Router for user-related endpoints.
|
|
3
|
+
Maintains backward compatibility with original API format.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from fastapi import APIRouter, Depends
|
|
9
|
+
from solace_ai_connector.common.log import log
|
|
10
|
+
|
|
11
|
+
from ...shared.auth_utils import get_current_user
|
|
12
|
+
|
|
13
|
+
router = APIRouter()
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@router.get("/me", response_model=dict[str, Any])
|
|
17
|
+
async def get_current_user_endpoint(
|
|
18
|
+
user: dict = Depends(get_current_user),
|
|
19
|
+
):
|
|
20
|
+
log.info("[GET /api/v1/users/me] Request received.")
|
|
21
|
+
|
|
22
|
+
# Get the user ID with proper priority
|
|
23
|
+
username = (
|
|
24
|
+
user.get("id") # Primary ID from AuthMiddleware
|
|
25
|
+
or user.get("user_id")
|
|
26
|
+
or user.get("username")
|
|
27
|
+
or user.get("email")
|
|
28
|
+
or "anonymous"
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
"username": username,
|
|
33
|
+
"authenticated": user.get("authenticated", False),
|
|
34
|
+
"auth_method": user.get("auth_method", "none"),
|
|
35
|
+
}
|