aixtools 0.2.8__tar.gz → 0.2.10__tar.gz
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 aixtools might be problematic. Click here for more details.
- {aixtools-0.2.8 → aixtools-0.2.10}/PKG-INFO +2 -2
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/_version.py +3 -3
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/a2a/google_sdk/pydantic_ai_adapter/agent_executor.py +74 -5
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/a2a/google_sdk/remote_agent_connection.py +16 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/a2a/google_sdk/utils.py +1 -1
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/auth/auth.py +29 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/utils/config.py +3 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/pyproject.toml +1 -1
- {aixtools-0.2.8 → aixtools-0.2.10}/README.md +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/.chainlit/config.toml +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/.chainlit/translations/bn.json +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/.chainlit/translations/en-US.json +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/.chainlit/translations/gu.json +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/.chainlit/translations/he-IL.json +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/.chainlit/translations/hi.json +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/.chainlit/translations/ja.json +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/.chainlit/translations/kn.json +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/.chainlit/translations/ml.json +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/.chainlit/translations/mr.json +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/.chainlit/translations/nl.json +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/.chainlit/translations/ta.json +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/.chainlit/translations/te.json +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/.chainlit/translations/zh-CN.json +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/__init__.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/a2a/app.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/a2a/google_sdk/__init__.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/a2a/google_sdk/pydantic_ai_adapter/storage.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/a2a/utils.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/agents/__init__.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/agents/agent.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/agents/agent_batch.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/agents/print_nodes.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/agents/prompt.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/app.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/auth/__init__.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/chainlit.md +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/compliance/__init__.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/compliance/private_data.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/context.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/db/__init__.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/db/database.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/db/vector_db.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/evals/__init__.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/evals/__main__.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/evals/dataset.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/evals/discovery.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/evals/run_evals.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/google/client.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/log_view/__init__.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/log_view/app.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/log_view/display.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/log_view/export.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/log_view/filters.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/log_view/log_utils.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/log_view/node_summary.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/logfilters/__init__.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/logfilters/context_filter.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/logging/__init__.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/logging/log_objects.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/logging/logging_config.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/logging/mcp_log_models.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/logging/mcp_logger.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/logging/model_patch_logging.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/logging/open_telemetry.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/mcp/__init__.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/mcp/client.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/mcp/example_client.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/mcp/example_server.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/mcp/fast_mcp_log.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/mcp/faulty_mcp.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/model_patch/model_patch.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/server/__init__.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/server/app_mounter.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/server/path.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/server/utils.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/testing/__init__.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/testing/aix_test_model.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/testing/mock_tool.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/testing/model_patch_cache.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/tools/doctor/__init__.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/tools/doctor/mcp_tool_doctor.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/tools/doctor/tool_doctor.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/tools/doctor/tool_recommendation.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/utils/__init__.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/utils/chainlit/cl_agent_show.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/utils/chainlit/cl_utils.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/utils/config_util.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/utils/enum_with_description.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/utils/files.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/utils/persisted_dict.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/utils/utils.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/vault/__init__.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools/vault/vault.py +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/aixtools.egg-info/SOURCES.txt +0 -0
- {aixtools-0.2.8 → aixtools-0.2.10}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aixtools
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.10
|
|
4
4
|
Summary: Tools for AI exploration and debugging
|
|
5
5
|
Requires-Python: >=3.11.2
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -9,7 +9,7 @@ Requires-Dist: cachebox>=5.0.1
|
|
|
9
9
|
Requires-Dist: chainlit>=2.5.5
|
|
10
10
|
Requires-Dist: colorlog>=6.9.0
|
|
11
11
|
Requires-Dist: fasta2a>=0.5.0
|
|
12
|
-
Requires-Dist: fastmcp>=2.
|
|
12
|
+
Requires-Dist: fastmcp>=2.11.0
|
|
13
13
|
Requires-Dist: hvac>=2.3.0
|
|
14
14
|
Requires-Dist: ipykernel>=6.29.5
|
|
15
15
|
Requires-Dist: langchain-chroma>=0.2.3
|
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '0.2.
|
|
32
|
-
__version_tuple__ = version_tuple = (0, 2,
|
|
31
|
+
__version__ = version = '0.2.10'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 2, 10)
|
|
33
33
|
|
|
34
|
-
__commit_id__ = commit_id = '
|
|
34
|
+
__commit_id__ = commit_id = 'ge6b757983'
|
{aixtools-0.2.8 → aixtools-0.2.10}/aixtools/a2a/google_sdk/pydantic_ai_adapter/agent_executor.py
RENAMED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import asyncio
|
|
1
2
|
from pathlib import Path
|
|
2
3
|
|
|
3
4
|
from a2a.server.agent_execution import AgentExecutor, RequestContext
|
|
@@ -54,10 +55,23 @@ def _task_failed_event(text: str, context_id: str | None, task_id: str | None) -
|
|
|
54
55
|
)
|
|
55
56
|
|
|
56
57
|
|
|
58
|
+
def _task_cancelled_event(text: str, context_id: str | None, task_id: str | None) -> TaskStatusUpdateEvent:
|
|
59
|
+
"""Creates a TaskStatusUpdateEvent indicating task cancellation."""
|
|
60
|
+
return TaskStatusUpdateEvent(
|
|
61
|
+
status=TaskStatus(
|
|
62
|
+
state=TaskState.canceled, message=new_agent_text_message(text=text, context_id=context_id, task_id=task_id)
|
|
63
|
+
),
|
|
64
|
+
final=True,
|
|
65
|
+
context_id=context_id,
|
|
66
|
+
task_id=task_id,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
|
|
57
70
|
class PydanticAgentExecutor(AgentExecutor):
|
|
58
71
|
def __init__(self, agent_parameters: AgentParameters):
|
|
59
72
|
self._agent_parameters = agent_parameters
|
|
60
73
|
self.history_storage = InMemoryHistoryStorage()
|
|
74
|
+
self._running_tasks: dict[str, asyncio.Task] = {} # Track running agent tasks for cancellation
|
|
61
75
|
|
|
62
76
|
def _convert_message_to_pydantic_parts(
|
|
63
77
|
self,
|
|
@@ -102,11 +116,27 @@ class PydanticAgentExecutor(AgentExecutor):
|
|
|
102
116
|
prompt = self._convert_message_to_pydantic_parts(session_tuple, message)
|
|
103
117
|
history_message = self.history_storage.get(task.id)
|
|
104
118
|
|
|
105
|
-
|
|
106
|
-
|
|
119
|
+
# Create and track the agent run task for cancellation
|
|
120
|
+
agent_task = asyncio.create_task(
|
|
121
|
+
agent.run(
|
|
107
122
|
user_prompt=prompt,
|
|
108
123
|
message_history=history_message,
|
|
109
124
|
)
|
|
125
|
+
)
|
|
126
|
+
self._running_tasks[task.id] = agent_task
|
|
127
|
+
|
|
128
|
+
try:
|
|
129
|
+
result = await agent_task
|
|
130
|
+
except asyncio.CancelledError:
|
|
131
|
+
# Task was cancelled, send cancellation event
|
|
132
|
+
await event_queue.enqueue_event(
|
|
133
|
+
_task_cancelled_event(
|
|
134
|
+
text="Task was cancelled",
|
|
135
|
+
context_id=context.context_id,
|
|
136
|
+
task_id=task.id,
|
|
137
|
+
)
|
|
138
|
+
)
|
|
139
|
+
return
|
|
110
140
|
except Exception as e:
|
|
111
141
|
await event_queue.enqueue_event(
|
|
112
142
|
_task_failed_event(
|
|
@@ -116,6 +146,9 @@ class PydanticAgentExecutor(AgentExecutor):
|
|
|
116
146
|
)
|
|
117
147
|
)
|
|
118
148
|
return
|
|
149
|
+
finally:
|
|
150
|
+
# Clean up the task from tracking
|
|
151
|
+
self._running_tasks.pop(task.id, None)
|
|
119
152
|
|
|
120
153
|
self.history_storage.store(task.id, result.all_messages())
|
|
121
154
|
|
|
@@ -185,9 +218,45 @@ class PydanticAgentExecutor(AgentExecutor):
|
|
|
185
218
|
)
|
|
186
219
|
)
|
|
187
220
|
|
|
188
|
-
async def cancel(self,
|
|
189
|
-
"""Cancel
|
|
190
|
-
|
|
221
|
+
async def cancel(self, context: RequestContext, event_queue: EventQueue) -> None:
|
|
222
|
+
"""Cancel the ongoing task identified by the task_id in the context.
|
|
223
|
+
|
|
224
|
+
Attempts to stop the running agent task and publishes a TaskStatusUpdateEvent
|
|
225
|
+
with state TaskState.canceled to the event_queue as per A2A SDK specification.
|
|
226
|
+
|
|
227
|
+
Args:
|
|
228
|
+
context: The request context containing the task ID to cancel.
|
|
229
|
+
event_queue: The queue to publish the cancellation status update to.
|
|
230
|
+
"""
|
|
231
|
+
task = context.current_task
|
|
232
|
+
if not task:
|
|
233
|
+
logger.warning("No task to cancel in context")
|
|
234
|
+
return
|
|
235
|
+
|
|
236
|
+
task_id = task.id
|
|
237
|
+
|
|
238
|
+
# Check if we have a running task to cancel
|
|
239
|
+
if task_id in self._running_tasks:
|
|
240
|
+
agent_task = self._running_tasks[task_id]
|
|
241
|
+
if not agent_task.done():
|
|
242
|
+
logger.info("Cancelling running agent task: %s", task_id)
|
|
243
|
+
agent_task.cancel()
|
|
244
|
+
# The cancellation event will be sent by the execute method's except block
|
|
245
|
+
return
|
|
246
|
+
|
|
247
|
+
# If no running task found, check if task is already in terminal state
|
|
248
|
+
if is_in_terminal_state(task):
|
|
249
|
+
logger.info("Task %s is already in terminal state: %s", task_id, task.status.state)
|
|
250
|
+
return
|
|
251
|
+
|
|
252
|
+
# Send cancellation event for tasks that aren't currently running
|
|
253
|
+
await event_queue.enqueue_event(
|
|
254
|
+
_task_cancelled_event(
|
|
255
|
+
text="Task cancelled",
|
|
256
|
+
context_id=context.context_id,
|
|
257
|
+
task_id=task_id,
|
|
258
|
+
)
|
|
259
|
+
)
|
|
191
260
|
|
|
192
261
|
def _build_agent(self, session_tuple: SessionIdTuple) -> Agent:
|
|
193
262
|
params = self._agent_parameters
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
+
from typing import Callable
|
|
2
3
|
|
|
3
4
|
from a2a.client import Client
|
|
4
5
|
from a2a.types import (
|
|
5
6
|
AgentCard,
|
|
6
7
|
Message,
|
|
7
8
|
Task,
|
|
9
|
+
TaskIdParams,
|
|
8
10
|
TaskQueryParams,
|
|
9
11
|
TaskState,
|
|
10
12
|
)
|
|
@@ -63,6 +65,7 @@ class RemoteAgentConnection:
|
|
|
63
65
|
*,
|
|
64
66
|
sleep_time: float = 0.2,
|
|
65
67
|
max_iter=1000,
|
|
68
|
+
on_task_submitted: Callable[[str], None] | None = None,
|
|
66
69
|
) -> Task | Message:
|
|
67
70
|
"""
|
|
68
71
|
Sends a message to the remote agent and polls for the task status at regular intervals.
|
|
@@ -75,6 +78,9 @@ class RemoteAgentConnection:
|
|
|
75
78
|
if isinstance(last_task, Message):
|
|
76
79
|
return last_task
|
|
77
80
|
|
|
81
|
+
if on_task_submitted:
|
|
82
|
+
on_task_submitted(last_task.id)
|
|
83
|
+
|
|
78
84
|
if is_in_terminal_or_interrupted_state(last_task):
|
|
79
85
|
return last_task
|
|
80
86
|
task_id = last_task.id
|
|
@@ -86,3 +92,13 @@ class RemoteAgentConnection:
|
|
|
86
92
|
|
|
87
93
|
timeout_seconds = max_iter * sleep_time
|
|
88
94
|
raise Exception(f"Task did not complete in {timeout_seconds} seconds") # pylint: disable=broad-exception-raised
|
|
95
|
+
|
|
96
|
+
async def cancel_task(self, task_id: str) -> Task:
|
|
97
|
+
"""
|
|
98
|
+
Cancels a task by its ID.
|
|
99
|
+
"""
|
|
100
|
+
try:
|
|
101
|
+
return await self._client.cancel_task(TaskIdParams(id=task_id))
|
|
102
|
+
except Exception as e:
|
|
103
|
+
logger.error("Exception found in cancel_task: %s", str(e))
|
|
104
|
+
raise e
|
|
@@ -40,7 +40,7 @@ class _AgentCardResolver:
|
|
|
40
40
|
|
|
41
41
|
def __init__(self, client: httpx.AsyncClient):
|
|
42
42
|
self._httpx_client = client
|
|
43
|
-
self._a2a_client_factory = ClientFactory(ClientConfig(httpx_client=self._httpx_client))
|
|
43
|
+
self._a2a_client_factory = ClientFactory(ClientConfig(httpx_client=self._httpx_client, polling=True))
|
|
44
44
|
self.clients: dict[str, RemoteAgentConnection] = {}
|
|
45
45
|
|
|
46
46
|
def register_agent_card(self, card: AgentCard):
|
|
@@ -7,7 +7,11 @@ import logging
|
|
|
7
7
|
|
|
8
8
|
import jwt
|
|
9
9
|
from fastapi import HTTPException
|
|
10
|
+
from fastmcp.server.auth.auth import AuthProvider
|
|
10
11
|
from jwt import ExpiredSignatureError, InvalidAudienceError, InvalidIssuerError, InvalidSignatureError, PyJWKClient
|
|
12
|
+
from mcp.server.auth.provider import (
|
|
13
|
+
AccessToken,
|
|
14
|
+
)
|
|
11
15
|
|
|
12
16
|
from aixtools.utils import config
|
|
13
17
|
|
|
@@ -147,3 +151,28 @@ class AccessTokenVerifier:
|
|
|
147
151
|
AuthTokenErrorCode.MISSING_GROUPS_ERROR,
|
|
148
152
|
f"Could not find any group in JWT token, matching: {self.authorized_groups}",
|
|
149
153
|
)
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
class AccessTokenAuthProvider(AuthProvider):
|
|
157
|
+
"""Authentication provider for MCP servers for validating, authorizing and extracting access tokens."""
|
|
158
|
+
|
|
159
|
+
def __init__(self) -> None:
|
|
160
|
+
super().__init__()
|
|
161
|
+
self.token_verifier = AccessTokenVerifier()
|
|
162
|
+
|
|
163
|
+
async def verify_token(self, token: str) -> AccessToken:
|
|
164
|
+
"""Verify the access token and return an AccessToken object."""
|
|
165
|
+
|
|
166
|
+
logger.info("Received verify token request")
|
|
167
|
+
claims = self.token_verifier.verify(token)
|
|
168
|
+
scopes = claims.get("scp", "")
|
|
169
|
+
self.token_verifier.authorize_claims(claims, scopes)
|
|
170
|
+
|
|
171
|
+
scopes_arr = []
|
|
172
|
+
if scopes:
|
|
173
|
+
scopes_arr = scopes.split(" ")
|
|
174
|
+
|
|
175
|
+
logger.info("Authorized the token")
|
|
176
|
+
return AccessToken(
|
|
177
|
+
token=token, client_id=self.token_verifier.api_id, scopes=scopes_arr, expires_at=claims.get("exp", None)
|
|
178
|
+
)
|
|
@@ -138,3 +138,6 @@ APP_TENANT_ID = get_variable_env("APP_TENANT_ID")
|
|
|
138
138
|
|
|
139
139
|
# used for token authorization check
|
|
140
140
|
APP_AUTHORIZED_GROUPS = get_variable_env("APP_AUTHORIZED_GROUPS", allow_empty=True)
|
|
141
|
+
|
|
142
|
+
# used to skip authorization in local tests if required.
|
|
143
|
+
SKIP_MCP_AUTHORIZATION = str2bool(get_variable_env("SKIP_MCP_AUTHORIZATION", True, False))
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|