mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-01-08 15:48:29 +00:00
Compare commits
2 Commits
devin/1739
...
devin/1746
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9bb8854c25 | ||
|
|
cfabb9fa78 |
59
examples/a2a_protocol_example.py
Normal file
59
examples/a2a_protocol_example.py
Normal file
@@ -0,0 +1,59 @@
|
||||
"""
|
||||
Example of using the A2A protocol with CrewAI.
|
||||
|
||||
This example demonstrates how to:
|
||||
1. Create an agent with A2A protocol support
|
||||
2. Start an A2A server for the agent
|
||||
3. Execute a task via the A2A protocol
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
import uvicorn
|
||||
from threading import Thread
|
||||
|
||||
from crewai import Agent
|
||||
from crewai.a2a import A2AServer, InMemoryTaskManager
|
||||
|
||||
|
||||
agent = Agent(
|
||||
role="Data Analyst",
|
||||
goal="Analyze data and provide insights",
|
||||
backstory="I am a data analyst with expertise in finding patterns and insights in data.",
|
||||
a2a_enabled=True,
|
||||
a2a_url="http://localhost:8000",
|
||||
)
|
||||
|
||||
|
||||
def start_server():
|
||||
"""Start the A2A server."""
|
||||
task_manager = InMemoryTaskManager()
|
||||
|
||||
server = A2AServer(task_manager=task_manager)
|
||||
|
||||
uvicorn.run(server.app, host="0.0.0.0", port=8000)
|
||||
|
||||
|
||||
async def execute_task_via_a2a():
|
||||
"""Execute a task via the A2A protocol."""
|
||||
await asyncio.sleep(2)
|
||||
|
||||
result = await agent.execute_task_via_a2a(
|
||||
task_description="Analyze the following data and provide insights: [1, 2, 3, 4, 5]",
|
||||
context="This is a simple example of using the A2A protocol.",
|
||||
)
|
||||
|
||||
print(f"Task result: {result}")
|
||||
|
||||
|
||||
async def main():
|
||||
"""Run the example."""
|
||||
server_thread = Thread(target=start_server)
|
||||
server_thread.daemon = True
|
||||
server_thread.start()
|
||||
|
||||
await execute_task_via_a2a()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -23,4 +23,9 @@ __all__ = [
|
||||
"LLM",
|
||||
"Flow",
|
||||
"Knowledge",
|
||||
"A2AAgentIntegration",
|
||||
"A2AClient",
|
||||
"A2AServer",
|
||||
]
|
||||
|
||||
from crewai.a2a import A2AAgentIntegration, A2AClient, A2AServer
|
||||
|
||||
16
src/crewai/a2a/__init__.py
Normal file
16
src/crewai/a2a/__init__.py
Normal file
@@ -0,0 +1,16 @@
|
||||
"""A2A protocol implementation for CrewAI."""
|
||||
|
||||
from crewai.a2a.agent import A2AAgentIntegration
|
||||
from crewai.a2a.client import A2AClient
|
||||
from crewai.a2a.config import A2AConfig
|
||||
from crewai.a2a.server import A2AServer
|
||||
from crewai.a2a.task_manager import InMemoryTaskManager, TaskManager
|
||||
|
||||
__all__ = [
|
||||
"A2AAgentIntegration",
|
||||
"A2AClient",
|
||||
"A2AServer",
|
||||
"TaskManager",
|
||||
"InMemoryTaskManager",
|
||||
"A2AConfig",
|
||||
]
|
||||
223
src/crewai/a2a/agent.py
Normal file
223
src/crewai/a2a/agent.py
Normal file
@@ -0,0 +1,223 @@
|
||||
"""
|
||||
A2A protocol agent integration for CrewAI.
|
||||
|
||||
This module implements the integration between CrewAI agents and the A2A protocol.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
import logging
|
||||
import uuid
|
||||
from typing import Any, Dict, List, Optional, Union
|
||||
|
||||
from crewai.a2a.client import A2AClient
|
||||
from crewai.a2a.task_manager import TaskManager
|
||||
from crewai.types.a2a import (
|
||||
Artifact,
|
||||
DataPart,
|
||||
FilePart,
|
||||
Message,
|
||||
Part,
|
||||
Task as A2ATask,
|
||||
TaskArtifactUpdateEvent,
|
||||
TaskState,
|
||||
TaskStatusUpdateEvent,
|
||||
TextPart,
|
||||
)
|
||||
|
||||
|
||||
class A2AAgentIntegration:
|
||||
"""Integration between CrewAI agents and the A2A protocol."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
task_manager: Optional[TaskManager] = None,
|
||||
client: Optional[A2AClient] = None,
|
||||
):
|
||||
"""Initialize the A2A agent integration.
|
||||
|
||||
Args:
|
||||
task_manager: The task manager to use for handling A2A tasks.
|
||||
client: The A2A client to use for sending tasks to other agents.
|
||||
"""
|
||||
self.task_manager = task_manager
|
||||
self.client = client
|
||||
self.logger = logging.getLogger(__name__)
|
||||
|
||||
async def execute_task_via_a2a(
|
||||
self,
|
||||
agent_url: str,
|
||||
task_description: str,
|
||||
context: Optional[str] = None,
|
||||
api_key: Optional[str] = None,
|
||||
timeout: int = 300,
|
||||
) -> str:
|
||||
"""Execute a task via the A2A protocol.
|
||||
|
||||
Args:
|
||||
agent_url: The URL of the agent to execute the task.
|
||||
task_description: The description of the task.
|
||||
context: Additional context for the task.
|
||||
api_key: The API key to use for authentication.
|
||||
timeout: The timeout for the task execution in seconds.
|
||||
|
||||
Returns:
|
||||
The result of the task execution.
|
||||
|
||||
Raises:
|
||||
TimeoutError: If the task execution times out.
|
||||
Exception: If there is an error executing the task.
|
||||
"""
|
||||
if not self.client:
|
||||
self.client = A2AClient(base_url=agent_url, api_key=api_key)
|
||||
|
||||
parts: List[Part] = [TextPart(text=task_description)]
|
||||
if context:
|
||||
parts.append(
|
||||
DataPart(
|
||||
data={"context": context},
|
||||
metadata={"type": "context"},
|
||||
)
|
||||
)
|
||||
|
||||
message = Message(role="user", parts=parts)
|
||||
|
||||
task_id = str(uuid.uuid4())
|
||||
|
||||
try:
|
||||
queue = await self.client.send_task_streaming(
|
||||
task_id=task_id,
|
||||
message=message,
|
||||
)
|
||||
|
||||
result = await self._wait_for_task_completion(queue, timeout)
|
||||
return result
|
||||
except Exception as e:
|
||||
self.logger.exception(f"Error executing task via A2A: {e}")
|
||||
raise
|
||||
|
||||
async def _wait_for_task_completion(
|
||||
self, queue: asyncio.Queue, timeout: int
|
||||
) -> str:
|
||||
"""Wait for a task to complete.
|
||||
|
||||
Args:
|
||||
queue: The queue to receive task updates from.
|
||||
timeout: The timeout for the task execution in seconds.
|
||||
|
||||
Returns:
|
||||
The result of the task execution.
|
||||
|
||||
Raises:
|
||||
TimeoutError: If the task execution times out.
|
||||
Exception: If there is an error executing the task.
|
||||
"""
|
||||
result = ""
|
||||
try:
|
||||
async def _timeout():
|
||||
await asyncio.sleep(timeout)
|
||||
await queue.put(TimeoutError(f"Task execution timed out after {timeout} seconds"))
|
||||
|
||||
timeout_task = asyncio.create_task(_timeout())
|
||||
|
||||
while True:
|
||||
event = await queue.get()
|
||||
|
||||
if isinstance(event, Exception):
|
||||
raise event
|
||||
|
||||
if isinstance(event, TaskStatusUpdateEvent):
|
||||
if event.status.state == TaskState.COMPLETED:
|
||||
if event.status.message:
|
||||
for part in event.status.message.parts:
|
||||
if isinstance(part, TextPart):
|
||||
result += part.text
|
||||
break
|
||||
elif event.status.state in [TaskState.FAILED, TaskState.CANCELED]:
|
||||
error_message = "Task failed"
|
||||
if event.status.message:
|
||||
for part in event.status.message.parts:
|
||||
if isinstance(part, TextPart):
|
||||
error_message = part.text
|
||||
raise Exception(error_message)
|
||||
elif isinstance(event, TaskArtifactUpdateEvent):
|
||||
for part in event.artifact.parts:
|
||||
if isinstance(part, TextPart):
|
||||
result += part.text
|
||||
finally:
|
||||
timeout_task.cancel()
|
||||
|
||||
return result
|
||||
|
||||
async def handle_a2a_task(
|
||||
self,
|
||||
task: A2ATask,
|
||||
agent_execute_func: Any,
|
||||
context: Optional[str] = None,
|
||||
) -> None:
|
||||
"""Handle an A2A task.
|
||||
|
||||
Args:
|
||||
task: The A2A task to handle.
|
||||
agent_execute_func: The function to execute the task.
|
||||
context: Additional context for the task.
|
||||
|
||||
Raises:
|
||||
Exception: If there is an error handling the task.
|
||||
"""
|
||||
if not self.task_manager:
|
||||
raise ValueError("Task manager is required to handle A2A tasks")
|
||||
|
||||
try:
|
||||
await self.task_manager.update_task_status(
|
||||
task_id=task.id,
|
||||
state=TaskState.WORKING,
|
||||
)
|
||||
|
||||
task_description = ""
|
||||
task_context = context or ""
|
||||
|
||||
if task.history and task.history[-1].role == "user":
|
||||
message = task.history[-1]
|
||||
for part in message.parts:
|
||||
if isinstance(part, TextPart):
|
||||
task_description += part.text
|
||||
elif isinstance(part, DataPart) and part.data.get("context"):
|
||||
task_context += part.data["context"]
|
||||
|
||||
try:
|
||||
result = await agent_execute_func(task_description, task_context)
|
||||
|
||||
response_message = Message(
|
||||
role="agent",
|
||||
parts=[TextPart(text=result)],
|
||||
)
|
||||
|
||||
await self.task_manager.update_task_status(
|
||||
task_id=task.id,
|
||||
state=TaskState.COMPLETED,
|
||||
message=response_message,
|
||||
)
|
||||
|
||||
artifact = Artifact(
|
||||
name="result",
|
||||
parts=[TextPart(text=result)],
|
||||
)
|
||||
await self.task_manager.add_task_artifact(
|
||||
task_id=task.id,
|
||||
artifact=artifact,
|
||||
)
|
||||
except Exception as e:
|
||||
error_message = Message(
|
||||
role="agent",
|
||||
parts=[TextPart(text=str(e))],
|
||||
)
|
||||
await self.task_manager.update_task_status(
|
||||
task_id=task.id,
|
||||
state=TaskState.FAILED,
|
||||
message=error_message,
|
||||
)
|
||||
raise
|
||||
except Exception as e:
|
||||
self.logger.exception(f"Error handling A2A task: {e}")
|
||||
raise
|
||||
470
src/crewai/a2a/client.py
Normal file
470
src/crewai/a2a/client.py
Normal file
@@ -0,0 +1,470 @@
|
||||
"""
|
||||
A2A protocol client for CrewAI.
|
||||
|
||||
This module implements the client for the A2A protocol in CrewAI.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
from typing import Any, Dict, List, Optional, TYPE_CHECKING, Union, cast
|
||||
|
||||
import aiohttp
|
||||
from pydantic import ValidationError
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from crewai.a2a.config import A2AConfig
|
||||
|
||||
from crewai.types.a2a import (
|
||||
A2AClientError,
|
||||
A2AClientHTTPError,
|
||||
A2AClientJSONError,
|
||||
Artifact,
|
||||
CancelTaskRequest,
|
||||
CancelTaskResponse,
|
||||
GetTaskPushNotificationRequest,
|
||||
GetTaskPushNotificationResponse,
|
||||
GetTaskRequest,
|
||||
GetTaskResponse,
|
||||
JSONRPCError,
|
||||
JSONRPCRequest,
|
||||
JSONRPCResponse,
|
||||
Message,
|
||||
MissingAPIKeyError,
|
||||
PushNotificationConfig,
|
||||
SendTaskRequest,
|
||||
SendTaskResponse,
|
||||
SendTaskStreamingRequest,
|
||||
SetTaskPushNotificationRequest,
|
||||
SetTaskPushNotificationResponse,
|
||||
Task,
|
||||
TaskArtifactUpdateEvent,
|
||||
TaskIdParams,
|
||||
TaskPushNotificationConfig,
|
||||
TaskQueryParams,
|
||||
TaskSendParams,
|
||||
TaskState,
|
||||
TaskStatusUpdateEvent,
|
||||
)
|
||||
|
||||
|
||||
class A2AClient:
|
||||
"""A2A protocol client implementation."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
base_url: str,
|
||||
api_key: Optional[str] = None,
|
||||
timeout: Optional[int] = None,
|
||||
config: Optional["A2AConfig"] = None,
|
||||
):
|
||||
"""Initialize the A2A client.
|
||||
|
||||
Args:
|
||||
base_url: The base URL of the A2A server.
|
||||
api_key: The API key to use for authentication.
|
||||
timeout: The timeout for HTTP requests in seconds.
|
||||
config: The A2A configuration. If provided, other parameters are ignored.
|
||||
"""
|
||||
if config:
|
||||
from crewai.a2a.config import A2AConfig
|
||||
self.config = config
|
||||
else:
|
||||
from crewai.a2a.config import A2AConfig
|
||||
self.config = A2AConfig()
|
||||
if api_key:
|
||||
self.config.api_key = api_key
|
||||
if timeout:
|
||||
self.config.client_timeout = timeout
|
||||
|
||||
self.base_url = base_url.rstrip("/")
|
||||
self.api_key = self.config.api_key or os.environ.get("A2A_API_KEY")
|
||||
self.timeout = self.config.client_timeout
|
||||
self.logger = logging.getLogger(__name__)
|
||||
|
||||
async def send_task(
|
||||
self,
|
||||
task_id: str,
|
||||
message: Message,
|
||||
session_id: Optional[str] = None,
|
||||
accepted_output_modes: Optional[List[str]] = None,
|
||||
push_notification: Optional[PushNotificationConfig] = None,
|
||||
history_length: Optional[int] = None,
|
||||
metadata: Optional[Dict[str, Any]] = None,
|
||||
) -> Task:
|
||||
"""Send a task to the A2A server.
|
||||
|
||||
Args:
|
||||
task_id: The ID of the task.
|
||||
message: The message to send.
|
||||
session_id: The session ID.
|
||||
accepted_output_modes: The accepted output modes.
|
||||
push_notification: The push notification configuration.
|
||||
history_length: The number of messages to include in the history.
|
||||
metadata: Additional metadata.
|
||||
|
||||
Returns:
|
||||
The created task.
|
||||
|
||||
Raises:
|
||||
MissingAPIKeyError: If no API key is provided.
|
||||
A2AClientHTTPError: If there is an HTTP error.
|
||||
A2AClientJSONError: If there is an error parsing the JSON response.
|
||||
A2AClientError: If there is any other error sending the task.
|
||||
"""
|
||||
params = TaskSendParams(
|
||||
id=task_id,
|
||||
sessionId=session_id,
|
||||
message=message,
|
||||
acceptedOutputModes=accepted_output_modes,
|
||||
pushNotification=push_notification,
|
||||
historyLength=history_length,
|
||||
metadata=metadata,
|
||||
)
|
||||
|
||||
request = SendTaskRequest(params=params)
|
||||
|
||||
try:
|
||||
response = await self._send_jsonrpc_request(request)
|
||||
|
||||
if response.error:
|
||||
raise A2AClientError(f"Error sending task: {response.error.message}")
|
||||
|
||||
if not response.result:
|
||||
raise A2AClientError("No result returned from send task request")
|
||||
|
||||
if isinstance(response.result, dict):
|
||||
return Task.model_validate(response.result)
|
||||
return cast(Task, response.result)
|
||||
except asyncio.TimeoutError as e:
|
||||
raise A2AClientError(f"Task request timed out: {e}")
|
||||
except aiohttp.ClientError as e:
|
||||
if isinstance(e, aiohttp.ClientResponseError):
|
||||
raise A2AClientHTTPError(e.status, str(e))
|
||||
else:
|
||||
raise A2AClientError(f"Client error: {e}")
|
||||
|
||||
async def send_task_streaming(
|
||||
self,
|
||||
task_id: str,
|
||||
message: Message,
|
||||
session_id: Optional[str] = None,
|
||||
accepted_output_modes: Optional[List[str]] = None,
|
||||
push_notification: Optional[PushNotificationConfig] = None,
|
||||
history_length: Optional[int] = None,
|
||||
metadata: Optional[Dict[str, Any]] = None,
|
||||
) -> asyncio.Queue:
|
||||
"""Send a task to the A2A server and subscribe to updates.
|
||||
|
||||
Args:
|
||||
task_id: The ID of the task.
|
||||
message: The message to send.
|
||||
session_id: The session ID.
|
||||
accepted_output_modes: The accepted output modes.
|
||||
push_notification: The push notification configuration.
|
||||
history_length: The number of messages to include in the history.
|
||||
metadata: Additional metadata.
|
||||
|
||||
Returns:
|
||||
A queue that will receive task updates.
|
||||
|
||||
Raises:
|
||||
A2AClientError: If there is an error sending the task.
|
||||
"""
|
||||
params = TaskSendParams(
|
||||
id=task_id,
|
||||
sessionId=session_id,
|
||||
message=message,
|
||||
acceptedOutputModes=accepted_output_modes,
|
||||
pushNotification=push_notification,
|
||||
historyLength=history_length,
|
||||
metadata=metadata,
|
||||
)
|
||||
|
||||
queue: asyncio.Queue = asyncio.Queue()
|
||||
|
||||
asyncio.create_task(
|
||||
self._handle_streaming_response(
|
||||
f"{self.base_url}/v1/tasks/sendSubscribe", params, queue
|
||||
)
|
||||
)
|
||||
|
||||
return queue
|
||||
|
||||
async def get_task(
|
||||
self, task_id: str, history_length: Optional[int] = None
|
||||
) -> Task:
|
||||
"""Get a task from the A2A server.
|
||||
|
||||
Args:
|
||||
task_id: The ID of the task.
|
||||
history_length: The number of messages to include in the history.
|
||||
|
||||
Returns:
|
||||
The task.
|
||||
|
||||
Raises:
|
||||
A2AClientError: If there is an error getting the task.
|
||||
"""
|
||||
params = TaskQueryParams(id=task_id, historyLength=history_length)
|
||||
request = GetTaskRequest(params=params)
|
||||
response = await self._send_jsonrpc_request(request)
|
||||
|
||||
if response.error:
|
||||
raise A2AClientError(f"Error getting task: {response.error.message}")
|
||||
|
||||
if not response.result:
|
||||
raise A2AClientError("No result returned from get task request")
|
||||
|
||||
return cast(Task, response.result)
|
||||
|
||||
async def cancel_task(self, task_id: str) -> Task:
|
||||
"""Cancel a task on the A2A server.
|
||||
|
||||
Args:
|
||||
task_id: The ID of the task.
|
||||
|
||||
Returns:
|
||||
The canceled task.
|
||||
|
||||
Raises:
|
||||
A2AClientError: If there is an error canceling the task.
|
||||
"""
|
||||
params = TaskIdParams(id=task_id)
|
||||
request = CancelTaskRequest(params=params)
|
||||
response = await self._send_jsonrpc_request(request)
|
||||
|
||||
if response.error:
|
||||
raise A2AClientError(f"Error canceling task: {response.error.message}")
|
||||
|
||||
if not response.result:
|
||||
raise A2AClientError("No result returned from cancel task request")
|
||||
|
||||
return cast(Task, response.result)
|
||||
|
||||
async def set_push_notification(
|
||||
self, task_id: str, config: PushNotificationConfig
|
||||
) -> PushNotificationConfig:
|
||||
"""Set push notification for a task.
|
||||
|
||||
Args:
|
||||
task_id: The ID of the task.
|
||||
config: The push notification configuration.
|
||||
|
||||
Returns:
|
||||
The push notification configuration.
|
||||
|
||||
Raises:
|
||||
A2AClientError: If there is an error setting the push notification.
|
||||
"""
|
||||
params = TaskPushNotificationConfig(id=task_id, pushNotificationConfig=config)
|
||||
request = SetTaskPushNotificationRequest(params=params)
|
||||
response = await self._send_jsonrpc_request(request)
|
||||
|
||||
if response.error:
|
||||
raise A2AClientError(
|
||||
f"Error setting push notification: {response.error.message}"
|
||||
)
|
||||
|
||||
if not response.result:
|
||||
raise A2AClientError(
|
||||
"No result returned from set push notification request"
|
||||
)
|
||||
|
||||
return cast(TaskPushNotificationConfig, response.result).pushNotificationConfig
|
||||
|
||||
async def get_push_notification(
|
||||
self, task_id: str
|
||||
) -> Optional[PushNotificationConfig]:
|
||||
"""Get push notification for a task.
|
||||
|
||||
Args:
|
||||
task_id: The ID of the task.
|
||||
|
||||
Returns:
|
||||
The push notification configuration, or None if not set.
|
||||
|
||||
Raises:
|
||||
A2AClientError: If there is an error getting the push notification.
|
||||
"""
|
||||
params = TaskIdParams(id=task_id)
|
||||
request = GetTaskPushNotificationRequest(params=params)
|
||||
response = await self._send_jsonrpc_request(request)
|
||||
|
||||
if response.error:
|
||||
raise A2AClientError(
|
||||
f"Error getting push notification: {response.error.message}"
|
||||
)
|
||||
|
||||
if not response.result:
|
||||
return None
|
||||
|
||||
return cast(TaskPushNotificationConfig, response.result).pushNotificationConfig
|
||||
|
||||
async def _send_jsonrpc_request(
|
||||
self, request: JSONRPCRequest
|
||||
) -> JSONRPCResponse:
|
||||
"""Send a JSON-RPC request to the A2A server.
|
||||
|
||||
Args:
|
||||
request: The JSON-RPC request.
|
||||
|
||||
Returns:
|
||||
The JSON-RPC response.
|
||||
|
||||
Raises:
|
||||
A2AClientError: If there is an error sending the request.
|
||||
"""
|
||||
if not self.api_key:
|
||||
raise MissingAPIKeyError(
|
||||
"API key is required. Set it in the constructor or as the A2A_API_KEY environment variable."
|
||||
)
|
||||
|
||||
headers = {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": f"Bearer {self.api_key}",
|
||||
}
|
||||
|
||||
try:
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.post(
|
||||
f"{self.base_url}/v1/jsonrpc",
|
||||
headers=headers,
|
||||
json=request.model_dump(),
|
||||
timeout=self.timeout,
|
||||
) as response:
|
||||
if response.status != 200:
|
||||
raise A2AClientHTTPError(
|
||||
response.status, await response.text()
|
||||
)
|
||||
|
||||
try:
|
||||
data = await response.json()
|
||||
except json.JSONDecodeError as e:
|
||||
raise A2AClientJSONError(str(e))
|
||||
|
||||
try:
|
||||
return JSONRPCResponse.model_validate(data)
|
||||
except ValidationError as e:
|
||||
raise A2AClientError(f"Invalid response: {e}")
|
||||
except aiohttp.ClientConnectorError as e:
|
||||
raise A2AClientHTTPError(status=0, message=f"Connection error: {e}")
|
||||
except aiohttp.ClientOSError as e:
|
||||
raise A2AClientHTTPError(status=0, message=f"OS error: {e}")
|
||||
except aiohttp.ServerDisconnectedError as e:
|
||||
raise A2AClientHTTPError(status=0, message=f"Server disconnected: {e}")
|
||||
except aiohttp.ClientResponseError as e:
|
||||
raise A2AClientHTTPError(e.status, str(e))
|
||||
except aiohttp.ClientError as e:
|
||||
raise A2AClientError(f"HTTP error: {e}")
|
||||
|
||||
async def _handle_streaming_response(
|
||||
self,
|
||||
url: str,
|
||||
params: TaskSendParams,
|
||||
queue: asyncio.Queue,
|
||||
) -> None:
|
||||
"""Handle a streaming response from the A2A server.
|
||||
|
||||
Args:
|
||||
url: The URL to send the request to.
|
||||
params: The task send parameters.
|
||||
queue: The queue to put events into.
|
||||
"""
|
||||
if not self.api_key:
|
||||
await queue.put(
|
||||
Exception(
|
||||
"API key is required. Set it in the constructor or as the A2A_API_KEY environment variable."
|
||||
)
|
||||
)
|
||||
return
|
||||
|
||||
headers = {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": f"Bearer {self.api_key}",
|
||||
"Accept": "text/event-stream",
|
||||
}
|
||||
|
||||
try:
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.post(
|
||||
url,
|
||||
headers=headers,
|
||||
json=params.model_dump(),
|
||||
timeout=self.timeout,
|
||||
) as response:
|
||||
if response.status != 200:
|
||||
await queue.put(
|
||||
A2AClientHTTPError(response.status, await response.text())
|
||||
)
|
||||
return
|
||||
|
||||
buffer = ""
|
||||
async for line in response.content:
|
||||
line = line.decode("utf-8")
|
||||
buffer += line
|
||||
|
||||
if buffer.endswith("\n\n"):
|
||||
event_data = self._parse_sse_event(buffer)
|
||||
buffer = ""
|
||||
|
||||
if event_data:
|
||||
event_type = event_data.get("event")
|
||||
data = event_data.get("data")
|
||||
|
||||
if event_type == "status":
|
||||
try:
|
||||
event = TaskStatusUpdateEvent.model_validate_json(data)
|
||||
await queue.put(event)
|
||||
|
||||
if event.final:
|
||||
break
|
||||
except ValidationError as e:
|
||||
await queue.put(
|
||||
A2AClientError(f"Invalid status event: {e}")
|
||||
)
|
||||
elif event_type == "artifact":
|
||||
try:
|
||||
event = TaskArtifactUpdateEvent.model_validate_json(data)
|
||||
await queue.put(event)
|
||||
except ValidationError as e:
|
||||
await queue.put(
|
||||
A2AClientError(f"Invalid artifact event: {e}")
|
||||
)
|
||||
except aiohttp.ClientConnectorError as e:
|
||||
await queue.put(A2AClientHTTPError(status=0, message=f"Connection error: {e}"))
|
||||
except aiohttp.ClientOSError as e:
|
||||
await queue.put(A2AClientHTTPError(status=0, message=f"OS error: {e}"))
|
||||
except aiohttp.ServerDisconnectedError as e:
|
||||
await queue.put(A2AClientHTTPError(status=0, message=f"Server disconnected: {e}"))
|
||||
except aiohttp.ClientResponseError as e:
|
||||
await queue.put(A2AClientHTTPError(e.status, str(e)))
|
||||
except aiohttp.ClientError as e:
|
||||
await queue.put(A2AClientError(f"HTTP error: {e}"))
|
||||
except asyncio.CancelledError:
|
||||
pass
|
||||
except Exception as e:
|
||||
await queue.put(A2AClientError(f"Error handling streaming response: {e}"))
|
||||
|
||||
def _parse_sse_event(self, data: str) -> Dict[str, str]:
|
||||
"""Parse an SSE event.
|
||||
|
||||
Args:
|
||||
data: The SSE event data.
|
||||
|
||||
Returns:
|
||||
A dictionary with the event type and data.
|
||||
"""
|
||||
result = {}
|
||||
for line in data.split("\n"):
|
||||
line = line.strip()
|
||||
if not line:
|
||||
continue
|
||||
|
||||
if line.startswith("event:"):
|
||||
result["event"] = line[6:].strip()
|
||||
elif line.startswith("data:"):
|
||||
result["data"] = line[5:].strip()
|
||||
|
||||
return result
|
||||
89
src/crewai/a2a/config.py
Normal file
89
src/crewai/a2a/config.py
Normal file
@@ -0,0 +1,89 @@
|
||||
"""
|
||||
Configuration management for A2A protocol in CrewAI.
|
||||
|
||||
This module provides configuration management for the A2A protocol implementation
|
||||
in CrewAI, including default values and environment variable support.
|
||||
"""
|
||||
|
||||
import os
|
||||
from typing import Dict, Optional, Union
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class A2AConfig(BaseModel):
|
||||
"""Configuration for A2A protocol."""
|
||||
|
||||
server_host: str = Field(
|
||||
default="0.0.0.0",
|
||||
description="Host to bind the A2A server to.",
|
||||
)
|
||||
server_port: int = Field(
|
||||
default=8000,
|
||||
description="Port to bind the A2A server to.",
|
||||
)
|
||||
enable_cors: bool = Field(
|
||||
default=True,
|
||||
description="Whether to enable CORS for the A2A server.",
|
||||
)
|
||||
cors_origins: Optional[list[str]] = Field(
|
||||
default=None,
|
||||
description="CORS origins to allow. If None, all origins are allowed.",
|
||||
)
|
||||
|
||||
client_timeout: int = Field(
|
||||
default=60,
|
||||
description="Timeout for A2A client requests in seconds.",
|
||||
)
|
||||
api_key: Optional[str] = Field(
|
||||
default=None,
|
||||
description="API key for A2A authentication.",
|
||||
)
|
||||
|
||||
task_ttl: int = Field(
|
||||
default=3600,
|
||||
description="Time-to-live for tasks in seconds.",
|
||||
)
|
||||
cleanup_interval: int = Field(
|
||||
default=300,
|
||||
description="Interval for cleaning up expired tasks in seconds.",
|
||||
)
|
||||
max_history_length: int = Field(
|
||||
default=100,
|
||||
description="Maximum number of messages to include in task history.",
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_env(cls) -> "A2AConfig":
|
||||
"""Create a configuration from environment variables.
|
||||
|
||||
Environment variables are prefixed with A2A_ and are uppercase.
|
||||
For example, A2A_SERVER_PORT=8080 will set server_port to 8080.
|
||||
|
||||
Returns:
|
||||
A2AConfig: The configuration.
|
||||
"""
|
||||
config_dict: Dict[str, Union[str, int, bool, list[str]]] = {}
|
||||
|
||||
if "A2A_SERVER_HOST" in os.environ:
|
||||
config_dict["server_host"] = os.environ["A2A_SERVER_HOST"]
|
||||
if "A2A_SERVER_PORT" in os.environ:
|
||||
config_dict["server_port"] = int(os.environ["A2A_SERVER_PORT"])
|
||||
if "A2A_ENABLE_CORS" in os.environ:
|
||||
config_dict["enable_cors"] = os.environ["A2A_ENABLE_CORS"].lower() == "true"
|
||||
if "A2A_CORS_ORIGINS" in os.environ:
|
||||
config_dict["cors_origins"] = os.environ["A2A_CORS_ORIGINS"].split(",")
|
||||
|
||||
if "A2A_CLIENT_TIMEOUT" in os.environ:
|
||||
config_dict["client_timeout"] = int(os.environ["A2A_CLIENT_TIMEOUT"])
|
||||
if "A2A_API_KEY" in os.environ:
|
||||
config_dict["api_key"] = os.environ["A2A_API_KEY"]
|
||||
|
||||
if "A2A_TASK_TTL" in os.environ:
|
||||
config_dict["task_ttl"] = int(os.environ["A2A_TASK_TTL"])
|
||||
if "A2A_CLEANUP_INTERVAL" in os.environ:
|
||||
config_dict["cleanup_interval"] = int(os.environ["A2A_CLEANUP_INTERVAL"])
|
||||
if "A2A_MAX_HISTORY_LENGTH" in os.environ:
|
||||
config_dict["max_history_length"] = int(os.environ["A2A_MAX_HISTORY_LENGTH"])
|
||||
|
||||
return cls(**config_dict)
|
||||
515
src/crewai/a2a/server.py
Normal file
515
src/crewai/a2a/server.py
Normal file
@@ -0,0 +1,515 @@
|
||||
"""
|
||||
A2A protocol server for CrewAI.
|
||||
|
||||
This module implements the server for the A2A protocol in CrewAI.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
import logging
|
||||
from typing import Any, Callable, Dict, List, Optional, Type, TYPE_CHECKING, Union
|
||||
|
||||
from fastapi import FastAPI, HTTPException, Request, Response
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.responses import JSONResponse, StreamingResponse
|
||||
from pydantic import ValidationError
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from crewai.a2a.config import A2AConfig
|
||||
|
||||
from crewai.a2a.task_manager import InMemoryTaskManager, TaskManager
|
||||
from crewai.types.a2a import (
|
||||
A2ARequest,
|
||||
CancelTaskRequest,
|
||||
CancelTaskResponse,
|
||||
ContentTypeNotSupportedError,
|
||||
GetTaskPushNotificationRequest,
|
||||
GetTaskPushNotificationResponse,
|
||||
GetTaskRequest,
|
||||
GetTaskResponse,
|
||||
InternalError,
|
||||
InvalidParamsError,
|
||||
InvalidRequestError,
|
||||
JSONParseError,
|
||||
JSONRPCError,
|
||||
JSONRPCRequest,
|
||||
JSONRPCResponse,
|
||||
MethodNotFoundError,
|
||||
SendTaskRequest,
|
||||
SendTaskResponse,
|
||||
SendTaskStreamingRequest,
|
||||
SendTaskStreamingResponse,
|
||||
SetTaskPushNotificationRequest,
|
||||
SetTaskPushNotificationResponse,
|
||||
Task,
|
||||
TaskArtifactUpdateEvent,
|
||||
TaskIdParams,
|
||||
TaskNotCancelableError,
|
||||
TaskNotFoundError,
|
||||
TaskPushNotificationConfig,
|
||||
TaskQueryParams,
|
||||
TaskSendParams,
|
||||
TaskState,
|
||||
TaskStatusUpdateEvent,
|
||||
UnsupportedOperationError,
|
||||
)
|
||||
|
||||
|
||||
class A2AServer:
|
||||
"""A2A protocol server implementation."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
task_manager: Optional[TaskManager] = None,
|
||||
enable_cors: Optional[bool] = None,
|
||||
cors_origins: Optional[List[str]] = None,
|
||||
config: Optional["A2AConfig"] = None,
|
||||
):
|
||||
"""Initialize the A2A server.
|
||||
|
||||
Args:
|
||||
task_manager: The task manager to use. If None, an InMemoryTaskManager will be created.
|
||||
enable_cors: Whether to enable CORS. If None, uses config value.
|
||||
cors_origins: The CORS origins to allow. If None, uses config value.
|
||||
config: The A2A configuration. If provided, other parameters are ignored.
|
||||
"""
|
||||
from crewai.a2a.config import A2AConfig
|
||||
self.config = config or A2AConfig.from_env()
|
||||
|
||||
enable_cors = enable_cors if enable_cors is not None else self.config.enable_cors
|
||||
cors_origins = cors_origins or self.config.cors_origins
|
||||
|
||||
self.app = FastAPI(
|
||||
title="A2A Protocol Server",
|
||||
description="""
|
||||
A2A (Agent-to-Agent) protocol server for CrewAI.
|
||||
|
||||
This server implements Google's A2A protocol specification, enabling interoperability
|
||||
between different agent systems. It provides endpoints for task creation, retrieval,
|
||||
cancellation, and streaming updates.
|
||||
""",
|
||||
version="1.0.0",
|
||||
docs_url="/docs",
|
||||
redoc_url="/redoc",
|
||||
openapi_tags=[
|
||||
{
|
||||
"name": "tasks",
|
||||
"description": "Operations for managing A2A tasks",
|
||||
},
|
||||
{
|
||||
"name": "jsonrpc",
|
||||
"description": "JSON-RPC interface for the A2A protocol",
|
||||
},
|
||||
],
|
||||
)
|
||||
self.task_manager = task_manager or InMemoryTaskManager()
|
||||
self.logger = logging.getLogger(__name__)
|
||||
|
||||
if enable_cors:
|
||||
self.app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=cors_origins or ["*"],
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
@self.app.post(
|
||||
"/v1/jsonrpc",
|
||||
summary="Handle JSON-RPC requests",
|
||||
description="""
|
||||
Process JSON-RPC requests for the A2A protocol.
|
||||
|
||||
This endpoint handles all JSON-RPC requests for the A2A protocol, including:
|
||||
- SendTask: Create a new task
|
||||
- GetTask: Retrieve a task by ID
|
||||
- CancelTask: Cancel a running task
|
||||
- SetTaskPushNotification: Configure push notifications for a task
|
||||
- GetTaskPushNotification: Retrieve push notification configuration for a task
|
||||
""",
|
||||
response_model=JSONRPCResponse,
|
||||
responses={
|
||||
200: {"description": "Successful response with result or error"},
|
||||
400: {"description": "Invalid request format or parameters"},
|
||||
500: {"description": "Internal server error during processing"},
|
||||
},
|
||||
tags=["jsonrpc"],
|
||||
)
|
||||
async def handle_jsonrpc(request: Request):
|
||||
return await self.handle_jsonrpc(request)
|
||||
|
||||
@self.app.post(
|
||||
"/v1/tasks/send",
|
||||
summary="Send a task to an agent",
|
||||
description="""
|
||||
Create a new task and send it to an agent for execution.
|
||||
|
||||
This endpoint allows clients to send tasks to agents for processing.
|
||||
The task is created with the provided parameters and immediately
|
||||
transitions to the WORKING state. The response includes the created
|
||||
task with its current status.
|
||||
""",
|
||||
response_model=Task,
|
||||
responses={
|
||||
200: {"description": "Task created successfully and processing started"},
|
||||
400: {"description": "Invalid request format or parameters"},
|
||||
500: {"description": "Internal server error during task creation or processing"},
|
||||
},
|
||||
tags=["tasks"],
|
||||
)
|
||||
async def handle_send_task(request: Request):
|
||||
return await self.handle_send_task(request)
|
||||
|
||||
@self.app.post(
|
||||
"/v1/tasks/sendSubscribe",
|
||||
summary="Send a task and subscribe to updates",
|
||||
description="""
|
||||
Create a new task and subscribe to status updates via Server-Sent Events (SSE).
|
||||
|
||||
This endpoint allows clients to send tasks to agents and receive real-time
|
||||
updates as the task progresses. The response is a streaming SSE connection
|
||||
that provides status updates and artifact notifications until the task
|
||||
reaches a terminal state (COMPLETED, FAILED, CANCELED, or EXPIRED).
|
||||
""",
|
||||
responses={
|
||||
200: {
|
||||
"description": "Streaming response with task updates",
|
||||
"content": {
|
||||
"text/event-stream": {
|
||||
"schema": {"type": "string"},
|
||||
"example": 'event: status\ndata: {"task_id": "123", "status": {"state": "WORKING"}}\n\n',
|
||||
}
|
||||
},
|
||||
},
|
||||
400: {"description": "Invalid request format or parameters"},
|
||||
500: {"description": "Internal server error during task creation or processing"},
|
||||
},
|
||||
tags=["tasks"],
|
||||
)
|
||||
async def handle_send_task_subscribe(request: Request):
|
||||
return await self.handle_send_task_subscribe(request)
|
||||
|
||||
@self.app.post(
|
||||
"/v1/tasks/{task_id}/cancel",
|
||||
summary="Cancel a task",
|
||||
description="""
|
||||
Cancel a running task by ID.
|
||||
|
||||
This endpoint allows clients to cancel a task that is currently in progress.
|
||||
The task must be in a non-terminal state (PENDING, WORKING) to be canceled.
|
||||
Once canceled, the task transitions to the CANCELED state and cannot be
|
||||
resumed. The response includes the updated task with its current status.
|
||||
""",
|
||||
response_model=Task,
|
||||
responses={
|
||||
200: {"description": "Task canceled successfully and status updated to CANCELED"},
|
||||
404: {"description": "Task not found or already expired"},
|
||||
409: {"description": "Task cannot be canceled (already in terminal state)"},
|
||||
500: {"description": "Internal server error during task cancellation"},
|
||||
},
|
||||
tags=["tasks"],
|
||||
)
|
||||
async def handle_cancel_task(task_id: str, request: Request):
|
||||
return await self.handle_cancel_task(task_id, request)
|
||||
|
||||
@self.app.get(
|
||||
"/v1/tasks/{task_id}",
|
||||
summary="Get task details",
|
||||
description="""
|
||||
Retrieve details of a task by ID.
|
||||
|
||||
This endpoint allows clients to retrieve the current state and details of a task.
|
||||
The response includes the task's status, history, and any associated metadata.
|
||||
Clients can specify the history_length parameter to limit the number of messages
|
||||
included in the response.
|
||||
""",
|
||||
response_model=Task,
|
||||
responses={
|
||||
200: {"description": "Task details retrieved successfully with current status"},
|
||||
404: {"description": "Task not found or expired"},
|
||||
500: {"description": "Internal server error during task retrieval"},
|
||||
},
|
||||
tags=["tasks"],
|
||||
)
|
||||
async def handle_get_task(task_id: str, request: Request):
|
||||
return await self.handle_get_task(task_id, request)
|
||||
|
||||
async def handle_jsonrpc(self, request: Request) -> JSONResponse:
|
||||
"""Handle JSON-RPC requests.
|
||||
|
||||
Args:
|
||||
request: The FastAPI request.
|
||||
|
||||
Returns:
|
||||
A JSON response.
|
||||
"""
|
||||
try:
|
||||
body = await request.json()
|
||||
except json.JSONDecodeError:
|
||||
return JSONResponse(
|
||||
content=JSONRPCResponse(
|
||||
id=None, error=JSONParseError()
|
||||
).model_dump(),
|
||||
status_code=400,
|
||||
)
|
||||
|
||||
try:
|
||||
if isinstance(body, list):
|
||||
responses = []
|
||||
for req_data in body:
|
||||
response = await self._process_jsonrpc_request(req_data)
|
||||
responses.append(response.model_dump())
|
||||
return JSONResponse(content=responses)
|
||||
else:
|
||||
response = await self._process_jsonrpc_request(body)
|
||||
return JSONResponse(content=response.model_dump())
|
||||
except Exception as e:
|
||||
self.logger.exception("Error processing JSON-RPC request")
|
||||
return JSONResponse(
|
||||
content=JSONRPCResponse(
|
||||
id=body.get("id") if isinstance(body, dict) else None,
|
||||
error=InternalError(message="Internal server error"),
|
||||
).model_dump(),
|
||||
status_code=500,
|
||||
)
|
||||
|
||||
async def _process_jsonrpc_request(
|
||||
self, request_data: Dict[str, Any]
|
||||
) -> JSONRPCResponse:
|
||||
"""Process a JSON-RPC request.
|
||||
|
||||
Args:
|
||||
request_data: The JSON-RPC request data.
|
||||
|
||||
Returns:
|
||||
A JSON-RPC response.
|
||||
"""
|
||||
if not isinstance(request_data, dict) or request_data.get("jsonrpc") != "2.0":
|
||||
return JSONRPCResponse(
|
||||
id=request_data.get("id") if isinstance(request_data, dict) else None,
|
||||
error=InvalidRequestError(),
|
||||
)
|
||||
|
||||
request_id = request_data.get("id")
|
||||
method = request_data.get("method")
|
||||
|
||||
if not method:
|
||||
return JSONRPCResponse(
|
||||
id=request_id,
|
||||
error=InvalidRequestError(message="Method is required"),
|
||||
)
|
||||
|
||||
try:
|
||||
request = A2ARequest.validate_python(request_data)
|
||||
except ValidationError as e:
|
||||
return JSONRPCResponse(
|
||||
id=request_id,
|
||||
error=InvalidParamsError(data=str(e)),
|
||||
)
|
||||
|
||||
try:
|
||||
if isinstance(request, SendTaskRequest):
|
||||
task = await self._handle_send_task(request.params)
|
||||
return SendTaskResponse(id=request_id, result=task)
|
||||
elif isinstance(request, GetTaskRequest):
|
||||
task = await self.task_manager.get_task(
|
||||
request.params.id, request.params.historyLength
|
||||
)
|
||||
return GetTaskResponse(id=request_id, result=task)
|
||||
elif isinstance(request, CancelTaskRequest):
|
||||
task = await self.task_manager.cancel_task(request.params.id)
|
||||
return CancelTaskResponse(id=request_id, result=task)
|
||||
elif isinstance(request, SetTaskPushNotificationRequest):
|
||||
config = await self.task_manager.set_push_notification(
|
||||
request.params.id, request.params.pushNotificationConfig
|
||||
)
|
||||
return SetTaskPushNotificationResponse(
|
||||
id=request_id, result=TaskPushNotificationConfig(id=request.params.id, pushNotificationConfig=config)
|
||||
)
|
||||
elif isinstance(request, GetTaskPushNotificationRequest):
|
||||
config = await self.task_manager.get_push_notification(
|
||||
request.params.id
|
||||
)
|
||||
if config:
|
||||
return GetTaskPushNotificationResponse(
|
||||
id=request_id, result=TaskPushNotificationConfig(id=request.params.id, pushNotificationConfig=config)
|
||||
)
|
||||
else:
|
||||
return GetTaskPushNotificationResponse(id=request_id, result=None)
|
||||
elif isinstance(request, SendTaskStreamingRequest):
|
||||
return JSONRPCResponse(
|
||||
id=request_id,
|
||||
error=UnsupportedOperationError(
|
||||
message="Streaming requests should be sent to the streaming endpoint"
|
||||
),
|
||||
)
|
||||
else:
|
||||
return JSONRPCResponse(
|
||||
id=request_id,
|
||||
error=MethodNotFoundError(),
|
||||
)
|
||||
except KeyError:
|
||||
return JSONRPCResponse(
|
||||
id=request_id,
|
||||
error=TaskNotFoundError(),
|
||||
)
|
||||
except Exception as e:
|
||||
self.logger.exception(f"Error handling {method} request")
|
||||
return JSONRPCResponse(
|
||||
id=request_id,
|
||||
error=InternalError(message="Internal server error"),
|
||||
)
|
||||
|
||||
async def handle_send_task(self, request: Request) -> JSONResponse:
|
||||
"""Handle send task requests.
|
||||
|
||||
Args:
|
||||
request: The FastAPI request.
|
||||
|
||||
Returns:
|
||||
A JSON response.
|
||||
"""
|
||||
try:
|
||||
body = await request.json()
|
||||
params = TaskSendParams.model_validate(body)
|
||||
task = await self._handle_send_task(params)
|
||||
return JSONResponse(content=task.model_dump())
|
||||
except ValidationError:
|
||||
return JSONResponse(
|
||||
content={"error": "Invalid request format or parameters"},
|
||||
status_code=400,
|
||||
)
|
||||
except Exception as e:
|
||||
self.logger.exception("Error handling send task request")
|
||||
return JSONResponse(
|
||||
content={"error": "Internal server error"},
|
||||
status_code=500,
|
||||
)
|
||||
|
||||
async def _handle_send_task(self, params: TaskSendParams) -> Task:
|
||||
"""Handle send task requests.
|
||||
|
||||
Args:
|
||||
params: The task send parameters.
|
||||
|
||||
Returns:
|
||||
The created task.
|
||||
"""
|
||||
task = await self.task_manager.create_task(
|
||||
task_id=params.id,
|
||||
session_id=params.sessionId,
|
||||
message=params.message,
|
||||
metadata=params.metadata,
|
||||
)
|
||||
|
||||
await self.task_manager.update_task_status(
|
||||
task_id=params.id,
|
||||
state=TaskState.WORKING,
|
||||
)
|
||||
|
||||
return task
|
||||
|
||||
async def handle_send_task_subscribe(self, request: Request) -> StreamingResponse:
|
||||
"""Handle send task subscribe requests.
|
||||
|
||||
Args:
|
||||
request: The FastAPI request.
|
||||
|
||||
Returns:
|
||||
A streaming response.
|
||||
"""
|
||||
try:
|
||||
body = await request.json()
|
||||
params = TaskSendParams.model_validate(body)
|
||||
|
||||
task = await self._handle_send_task(params)
|
||||
|
||||
queue = await self.task_manager.subscribe_to_task(params.id)
|
||||
|
||||
return StreamingResponse(
|
||||
self._stream_task_updates(params.id, queue),
|
||||
media_type="text/event-stream",
|
||||
)
|
||||
except ValidationError:
|
||||
return JSONResponse(
|
||||
content={"error": "Invalid request format or parameters"},
|
||||
status_code=400,
|
||||
)
|
||||
except Exception as e:
|
||||
self.logger.exception("Error handling send task subscribe request")
|
||||
return JSONResponse(
|
||||
content={"error": "Internal server error"},
|
||||
status_code=500,
|
||||
)
|
||||
|
||||
async def _stream_task_updates(
|
||||
self, task_id: str, queue: asyncio.Queue
|
||||
) -> None:
|
||||
"""Stream task updates.
|
||||
|
||||
Args:
|
||||
task_id: The ID of the task.
|
||||
queue: The queue to receive updates from.
|
||||
|
||||
Yields:
|
||||
SSE formatted events.
|
||||
"""
|
||||
try:
|
||||
while True:
|
||||
event = await queue.get()
|
||||
|
||||
if isinstance(event, TaskStatusUpdateEvent):
|
||||
event_type = "status"
|
||||
elif isinstance(event, TaskArtifactUpdateEvent):
|
||||
event_type = "artifact"
|
||||
else:
|
||||
event_type = "unknown"
|
||||
|
||||
data = json.dumps(event.model_dump())
|
||||
yield f"event: {event_type}\ndata: {data}\n\n"
|
||||
|
||||
if isinstance(event, TaskStatusUpdateEvent) and event.final:
|
||||
break
|
||||
finally:
|
||||
await self.task_manager.unsubscribe_from_task(task_id, queue)
|
||||
|
||||
async def handle_get_task(self, task_id: str, request: Request) -> JSONResponse:
|
||||
"""Handle get task requests.
|
||||
|
||||
Args:
|
||||
task_id: The ID of the task.
|
||||
request: The FastAPI request.
|
||||
|
||||
Returns:
|
||||
A JSON response.
|
||||
"""
|
||||
try:
|
||||
history_length = request.query_params.get("historyLength")
|
||||
history_length = int(history_length) if history_length else None
|
||||
|
||||
task = await self.task_manager.get_task(task_id, history_length)
|
||||
return JSONResponse(content=task.model_dump())
|
||||
except KeyError:
|
||||
raise HTTPException(status_code=404, detail=f"Task {task_id} not found")
|
||||
except Exception as e:
|
||||
self.logger.exception(f"Error handling get task request for {task_id}")
|
||||
raise HTTPException(status_code=500, detail="Internal server error")
|
||||
|
||||
async def handle_cancel_task(self, task_id: str, request: Request) -> JSONResponse:
|
||||
"""Handle cancel task requests.
|
||||
|
||||
Args:
|
||||
task_id: The ID of the task.
|
||||
request: The FastAPI request.
|
||||
|
||||
Returns:
|
||||
A JSON response.
|
||||
"""
|
||||
try:
|
||||
task = await self.task_manager.cancel_task(task_id)
|
||||
return JSONResponse(content=task.model_dump())
|
||||
except KeyError:
|
||||
raise HTTPException(status_code=404, detail=f"Task {task_id} not found")
|
||||
except Exception as e:
|
||||
self.logger.exception(f"Error handling cancel task request for {task_id}")
|
||||
raise HTTPException(status_code=500, detail="Internal server error")
|
||||
522
src/crewai/a2a/task_manager.py
Normal file
522
src/crewai/a2a/task_manager.py
Normal file
@@ -0,0 +1,522 @@
|
||||
"""
|
||||
A2A protocol task manager for CrewAI.
|
||||
|
||||
This module implements the task manager for the A2A protocol in CrewAI.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
from abc import ABC, abstractmethod
|
||||
from datetime import datetime
|
||||
from typing import Any, Dict, List, Optional, Set, TYPE_CHECKING, Union
|
||||
from uuid import uuid4
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from crewai.a2a.config import A2AConfig
|
||||
|
||||
from crewai.types.a2a import (
|
||||
Artifact,
|
||||
Message,
|
||||
PushNotificationConfig,
|
||||
Task,
|
||||
TaskArtifactUpdateEvent,
|
||||
TaskState,
|
||||
TaskStatus,
|
||||
TaskStatusUpdateEvent,
|
||||
)
|
||||
|
||||
|
||||
class TaskManager(ABC):
|
||||
"""Abstract base class for A2A task managers."""
|
||||
|
||||
@abstractmethod
|
||||
async def create_task(
|
||||
self,
|
||||
task_id: str,
|
||||
session_id: Optional[str] = None,
|
||||
message: Optional[Message] = None,
|
||||
metadata: Optional[Dict[str, Any]] = None,
|
||||
) -> Task:
|
||||
"""Create a new task.
|
||||
|
||||
Args:
|
||||
task_id: The ID of the task.
|
||||
session_id: The session ID.
|
||||
message: The initial message.
|
||||
metadata: Additional metadata.
|
||||
|
||||
Returns:
|
||||
The created task.
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def get_task(
|
||||
self, task_id: str, history_length: Optional[int] = None
|
||||
) -> Task:
|
||||
"""Get a task by ID.
|
||||
|
||||
Args:
|
||||
task_id: The ID of the task.
|
||||
history_length: The number of messages to include in the history.
|
||||
|
||||
Returns:
|
||||
The task.
|
||||
|
||||
Raises:
|
||||
KeyError: If the task is not found.
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def update_task_status(
|
||||
self,
|
||||
task_id: str,
|
||||
state: TaskState,
|
||||
message: Optional[Message] = None,
|
||||
metadata: Optional[Dict[str, Any]] = None,
|
||||
) -> TaskStatusUpdateEvent:
|
||||
"""Update the status of a task.
|
||||
|
||||
Args:
|
||||
task_id: The ID of the task.
|
||||
state: The new state of the task.
|
||||
message: An optional message to include with the status update.
|
||||
metadata: Additional metadata.
|
||||
|
||||
Returns:
|
||||
The task status update event.
|
||||
|
||||
Raises:
|
||||
KeyError: If the task is not found.
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def add_task_artifact(
|
||||
self,
|
||||
task_id: str,
|
||||
artifact: Artifact,
|
||||
metadata: Optional[Dict[str, Any]] = None,
|
||||
) -> TaskArtifactUpdateEvent:
|
||||
"""Add an artifact to a task.
|
||||
|
||||
Args:
|
||||
task_id: The ID of the task.
|
||||
artifact: The artifact to add.
|
||||
metadata: Additional metadata.
|
||||
|
||||
Returns:
|
||||
The task artifact update event.
|
||||
|
||||
Raises:
|
||||
KeyError: If the task is not found.
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def cancel_task(self, task_id: str) -> Task:
|
||||
"""Cancel a task.
|
||||
|
||||
Args:
|
||||
task_id: The ID of the task.
|
||||
|
||||
Returns:
|
||||
The canceled task.
|
||||
|
||||
Raises:
|
||||
KeyError: If the task is not found.
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def set_push_notification(
|
||||
self, task_id: str, config: PushNotificationConfig
|
||||
) -> PushNotificationConfig:
|
||||
"""Set push notification for a task.
|
||||
|
||||
Args:
|
||||
task_id: The ID of the task.
|
||||
config: The push notification configuration.
|
||||
|
||||
Returns:
|
||||
The push notification configuration.
|
||||
|
||||
Raises:
|
||||
KeyError: If the task is not found.
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def get_push_notification(
|
||||
self, task_id: str
|
||||
) -> Optional[PushNotificationConfig]:
|
||||
"""Get push notification for a task.
|
||||
|
||||
Args:
|
||||
task_id: The ID of the task.
|
||||
|
||||
Returns:
|
||||
The push notification configuration, or None if not set.
|
||||
|
||||
Raises:
|
||||
KeyError: If the task is not found.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class InMemoryTaskManager(TaskManager):
|
||||
"""In-memory implementation of the A2A task manager."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
task_ttl: Optional[int] = None,
|
||||
cleanup_interval: Optional[int] = None,
|
||||
config: Optional["A2AConfig"] = None,
|
||||
):
|
||||
"""Initialize the in-memory task manager.
|
||||
|
||||
Args:
|
||||
task_ttl: Time to live for tasks in seconds. Default is 1 hour.
|
||||
cleanup_interval: Interval for cleaning up expired tasks in seconds. Default is 5 minutes.
|
||||
config: The A2A configuration. If provided, other parameters are ignored.
|
||||
"""
|
||||
from crewai.a2a.config import A2AConfig
|
||||
self.config = config or A2AConfig.from_env()
|
||||
|
||||
self._task_ttl = task_ttl if task_ttl is not None else self.config.task_ttl
|
||||
self._cleanup_interval = cleanup_interval if cleanup_interval is not None else self.config.cleanup_interval
|
||||
|
||||
self._tasks: Dict[str, Task] = {}
|
||||
self._push_notifications: Dict[str, PushNotificationConfig] = {}
|
||||
self._task_subscribers: Dict[str, Set[asyncio.Queue]] = {}
|
||||
self._task_timestamps: Dict[str, datetime] = {}
|
||||
self._logger = logging.getLogger(__name__)
|
||||
self._cleanup_task = None
|
||||
|
||||
try:
|
||||
if asyncio.get_running_loop():
|
||||
self._cleanup_task = asyncio.create_task(self._periodic_cleanup())
|
||||
except RuntimeError:
|
||||
self._logger.info("No running event loop, periodic cleanup disabled")
|
||||
|
||||
async def create_task(
|
||||
self,
|
||||
task_id: str,
|
||||
session_id: Optional[str] = None,
|
||||
message: Optional[Message] = None,
|
||||
metadata: Optional[Dict[str, Any]] = None,
|
||||
) -> Task:
|
||||
"""Create a new task.
|
||||
|
||||
Args:
|
||||
task_id: The ID of the task.
|
||||
session_id: The session ID.
|
||||
message: The initial message.
|
||||
metadata: Additional metadata.
|
||||
|
||||
Returns:
|
||||
The created task.
|
||||
"""
|
||||
if task_id in self._tasks:
|
||||
return self._tasks[task_id]
|
||||
|
||||
session_id = session_id or uuid4().hex
|
||||
status = TaskStatus(
|
||||
state=TaskState.SUBMITTED,
|
||||
message=message,
|
||||
timestamp=datetime.now(),
|
||||
previous_state=None, # Initial state has no previous state
|
||||
)
|
||||
|
||||
task = Task(
|
||||
id=task_id,
|
||||
sessionId=session_id,
|
||||
status=status,
|
||||
artifacts=[],
|
||||
history=[message] if message else [],
|
||||
metadata=metadata or {},
|
||||
)
|
||||
|
||||
self._tasks[task_id] = task
|
||||
self._task_subscribers[task_id] = set()
|
||||
self._task_timestamps[task_id] = datetime.now()
|
||||
return task
|
||||
|
||||
async def get_task(
|
||||
self, task_id: str, history_length: Optional[int] = None
|
||||
) -> Task:
|
||||
"""Get a task by ID.
|
||||
|
||||
Args:
|
||||
task_id: The ID of the task.
|
||||
history_length: The number of messages to include in the history.
|
||||
|
||||
Returns:
|
||||
The task.
|
||||
|
||||
Raises:
|
||||
KeyError: If the task is not found.
|
||||
"""
|
||||
if task_id not in self._tasks:
|
||||
raise KeyError(f"Task {task_id} not found")
|
||||
|
||||
task = self._tasks[task_id]
|
||||
if history_length is not None and task.history:
|
||||
task_copy = task.model_copy(deep=True)
|
||||
task_copy.history = task.history[-history_length:]
|
||||
return task_copy
|
||||
return task
|
||||
|
||||
async def update_task_status(
|
||||
self,
|
||||
task_id: str,
|
||||
state: TaskState,
|
||||
message: Optional[Message] = None,
|
||||
metadata: Optional[Dict[str, Any]] = None,
|
||||
) -> TaskStatusUpdateEvent:
|
||||
"""Update the status of a task.
|
||||
|
||||
Args:
|
||||
task_id: The ID of the task.
|
||||
state: The new state of the task.
|
||||
message: An optional message to include with the status update.
|
||||
metadata: Additional metadata.
|
||||
|
||||
Returns:
|
||||
The task status update event.
|
||||
|
||||
Raises:
|
||||
KeyError: If the task is not found.
|
||||
"""
|
||||
if task_id not in self._tasks:
|
||||
raise KeyError(f"Task {task_id} not found")
|
||||
|
||||
task = self._tasks[task_id]
|
||||
task = self._tasks[task_id]
|
||||
previous_state = task.status.state if task.status else None
|
||||
|
||||
if previous_state and not TaskState.is_valid_transition(previous_state, state):
|
||||
raise ValueError(f"Invalid state transition from {previous_state} to {state}")
|
||||
|
||||
status = TaskStatus(
|
||||
state=state,
|
||||
message=message,
|
||||
timestamp=datetime.now(),
|
||||
previous_state=previous_state,
|
||||
)
|
||||
task.status = status
|
||||
|
||||
if message and task.history is not None:
|
||||
task.history.append(message)
|
||||
|
||||
self._task_timestamps[task_id] = datetime.now()
|
||||
|
||||
event = TaskStatusUpdateEvent(
|
||||
id=task_id,
|
||||
status=status,
|
||||
final=state in [TaskState.COMPLETED, TaskState.CANCELED, TaskState.FAILED, TaskState.EXPIRED],
|
||||
metadata=metadata or {},
|
||||
)
|
||||
|
||||
await self._notify_subscribers(task_id, event)
|
||||
|
||||
return event
|
||||
|
||||
async def add_task_artifact(
|
||||
self,
|
||||
task_id: str,
|
||||
artifact: Artifact,
|
||||
metadata: Optional[Dict[str, Any]] = None,
|
||||
) -> TaskArtifactUpdateEvent:
|
||||
"""Add an artifact to a task.
|
||||
|
||||
Args:
|
||||
task_id: The ID of the task.
|
||||
artifact: The artifact to add.
|
||||
metadata: Additional metadata.
|
||||
|
||||
Returns:
|
||||
The task artifact update event.
|
||||
|
||||
Raises:
|
||||
KeyError: If the task is not found.
|
||||
"""
|
||||
if task_id not in self._tasks:
|
||||
raise KeyError(f"Task {task_id} not found")
|
||||
|
||||
task = self._tasks[task_id]
|
||||
if task.artifacts is None:
|
||||
task.artifacts = []
|
||||
|
||||
if artifact.append and task.artifacts:
|
||||
for existing in task.artifacts:
|
||||
if existing.name == artifact.name:
|
||||
existing.parts.extend(artifact.parts)
|
||||
existing.lastChunk = artifact.lastChunk
|
||||
break
|
||||
else:
|
||||
task.artifacts.append(artifact)
|
||||
else:
|
||||
task.artifacts.append(artifact)
|
||||
|
||||
event = TaskArtifactUpdateEvent(
|
||||
id=task_id,
|
||||
artifact=artifact,
|
||||
metadata=metadata or {},
|
||||
)
|
||||
|
||||
await self._notify_subscribers(task_id, event)
|
||||
|
||||
return event
|
||||
|
||||
async def cancel_task(self, task_id: str) -> Task:
|
||||
"""Cancel a task.
|
||||
|
||||
Args:
|
||||
task_id: The ID of the task.
|
||||
|
||||
Returns:
|
||||
The canceled task.
|
||||
|
||||
Raises:
|
||||
KeyError: If the task is not found.
|
||||
"""
|
||||
if task_id not in self._tasks:
|
||||
raise KeyError(f"Task {task_id} not found")
|
||||
|
||||
task = self._tasks[task_id]
|
||||
|
||||
if task.status.state not in [TaskState.COMPLETED, TaskState.CANCELED, TaskState.FAILED]:
|
||||
await self.update_task_status(task_id, TaskState.CANCELED)
|
||||
|
||||
return task
|
||||
|
||||
async def set_push_notification(
|
||||
self, task_id: str, config: PushNotificationConfig
|
||||
) -> PushNotificationConfig:
|
||||
"""Set push notification for a task.
|
||||
|
||||
Args:
|
||||
task_id: The ID of the task.
|
||||
config: The push notification configuration.
|
||||
|
||||
Returns:
|
||||
The push notification configuration.
|
||||
|
||||
Raises:
|
||||
KeyError: If the task is not found.
|
||||
"""
|
||||
if task_id not in self._tasks:
|
||||
raise KeyError(f"Task {task_id} not found")
|
||||
|
||||
self._push_notifications[task_id] = config
|
||||
return config
|
||||
|
||||
async def get_push_notification(
|
||||
self, task_id: str
|
||||
) -> Optional[PushNotificationConfig]:
|
||||
"""Get push notification for a task.
|
||||
|
||||
Args:
|
||||
task_id: The ID of the task.
|
||||
|
||||
Returns:
|
||||
The push notification configuration, or None if not set.
|
||||
|
||||
Raises:
|
||||
KeyError: If the task is not found.
|
||||
"""
|
||||
if task_id not in self._tasks:
|
||||
raise KeyError(f"Task {task_id} not found")
|
||||
|
||||
return self._push_notifications.get(task_id)
|
||||
|
||||
async def subscribe_to_task(self, task_id: str) -> asyncio.Queue:
|
||||
"""Subscribe to task updates.
|
||||
|
||||
Args:
|
||||
task_id: The ID of the task.
|
||||
|
||||
Returns:
|
||||
A queue that will receive task updates.
|
||||
|
||||
Raises:
|
||||
KeyError: If the task is not found.
|
||||
"""
|
||||
if task_id not in self._tasks:
|
||||
raise KeyError(f"Task {task_id} not found")
|
||||
|
||||
queue: asyncio.Queue = asyncio.Queue()
|
||||
self._task_subscribers.setdefault(task_id, set()).add(queue)
|
||||
return queue
|
||||
|
||||
async def unsubscribe_from_task(self, task_id: str, queue: asyncio.Queue) -> None:
|
||||
"""Unsubscribe from task updates.
|
||||
|
||||
Args:
|
||||
task_id: The ID of the task.
|
||||
queue: The queue to unsubscribe.
|
||||
"""
|
||||
if task_id in self._task_subscribers:
|
||||
self._task_subscribers[task_id].discard(queue)
|
||||
|
||||
async def _notify_subscribers(
|
||||
self,
|
||||
task_id: str,
|
||||
event: Union[TaskStatusUpdateEvent, TaskArtifactUpdateEvent],
|
||||
) -> None:
|
||||
"""Notify subscribers of a task update.
|
||||
|
||||
Args:
|
||||
task_id: The ID of the task.
|
||||
event: The event to send to subscribers.
|
||||
"""
|
||||
if task_id in self._task_subscribers:
|
||||
for queue in self._task_subscribers[task_id]:
|
||||
await queue.put(event)
|
||||
|
||||
async def _periodic_cleanup(self) -> None:
|
||||
"""Periodically clean up expired tasks."""
|
||||
while True:
|
||||
try:
|
||||
await asyncio.sleep(self._cleanup_interval)
|
||||
await self._cleanup_expired_tasks()
|
||||
except asyncio.CancelledError:
|
||||
break
|
||||
except Exception as e:
|
||||
self._logger.exception(f"Error during periodic cleanup: {e}")
|
||||
|
||||
async def _cleanup_expired_tasks(self) -> None:
|
||||
"""Clean up expired tasks."""
|
||||
now = datetime.now()
|
||||
expired_tasks = []
|
||||
|
||||
for task_id, timestamp in self._task_timestamps.items():
|
||||
if (now - timestamp).total_seconds() > self._task_ttl:
|
||||
expired_tasks.append(task_id)
|
||||
|
||||
for task_id in expired_tasks:
|
||||
self._logger.info(f"Cleaning up expired task: {task_id}")
|
||||
self._tasks.pop(task_id, None)
|
||||
self._push_notifications.pop(task_id, None)
|
||||
self._task_timestamps.pop(task_id, None)
|
||||
|
||||
if task_id in self._task_subscribers:
|
||||
previous_state = None
|
||||
if task_id in self._tasks and self._tasks[task_id].status:
|
||||
previous_state = self._tasks[task_id].status.state
|
||||
|
||||
status = TaskStatus(
|
||||
state=TaskState.EXPIRED,
|
||||
timestamp=now,
|
||||
previous_state=previous_state,
|
||||
)
|
||||
event = TaskStatusUpdateEvent(
|
||||
task_id=task_id,
|
||||
status=status,
|
||||
final=True,
|
||||
)
|
||||
await self._notify_subscribers(task_id, event)
|
||||
|
||||
self._task_subscribers.pop(task_id, None)
|
||||
@@ -5,6 +5,7 @@ from typing import Any, Dict, List, Literal, Optional, Union
|
||||
|
||||
from pydantic import Field, InstanceOf, PrivateAttr, model_validator
|
||||
|
||||
from crewai.a2a import A2AAgentIntegration
|
||||
from crewai.agents import CacheHandler
|
||||
from crewai.agents.agent_builder.base_agent import BaseAgent
|
||||
from crewai.agents.crew_agent_executor import CrewAgentExecutor
|
||||
@@ -131,14 +132,29 @@ class Agent(BaseAgent):
|
||||
default=None,
|
||||
description="Knowledge sources for the agent.",
|
||||
)
|
||||
a2a_enabled: bool = Field(
|
||||
default=False,
|
||||
description="Whether the agent supports the A2A protocol.",
|
||||
)
|
||||
a2a_url: Optional[str] = Field(
|
||||
default=None,
|
||||
description="The URL where the agent's A2A server is hosted.",
|
||||
)
|
||||
_knowledge: Optional[Knowledge] = PrivateAttr(
|
||||
default=None,
|
||||
)
|
||||
_a2a_integration: Optional[A2AAgentIntegration] = PrivateAttr(
|
||||
default=None,
|
||||
)
|
||||
|
||||
@model_validator(mode="after")
|
||||
def post_init_setup(self):
|
||||
self._set_knowledge()
|
||||
self.agent_ops_agent_name = self.role
|
||||
|
||||
if self.a2a_enabled:
|
||||
self._a2a_integration = A2AAgentIntegration()
|
||||
|
||||
unaccepted_attributes = [
|
||||
"AWS_ACCESS_KEY_ID",
|
||||
"AWS_SECRET_ACCESS_KEY",
|
||||
@@ -355,6 +371,103 @@ class Agent(BaseAgent):
|
||||
result = tool_result["result"]
|
||||
|
||||
return result
|
||||
|
||||
async def execute_task_via_a2a(
|
||||
self,
|
||||
task_description: str,
|
||||
context: Optional[str] = None,
|
||||
agent_url: Optional[str] = None,
|
||||
api_key: Optional[str] = None,
|
||||
timeout: int = 300,
|
||||
) -> str:
|
||||
"""Execute a task via the A2A protocol.
|
||||
|
||||
Args:
|
||||
task_description: The description of the task.
|
||||
context: Additional context for the task.
|
||||
agent_url: The URL of the agent to execute the task. Defaults to self.a2a_url.
|
||||
api_key: The API key to use for authentication.
|
||||
timeout: The timeout for the task execution in seconds.
|
||||
|
||||
Returns:
|
||||
The result of the task execution.
|
||||
|
||||
Raises:
|
||||
ValueError: If A2A is not enabled or no agent URL is provided.
|
||||
TimeoutError: If the task execution times out.
|
||||
Exception: If there is an error executing the task.
|
||||
"""
|
||||
if not self.a2a_enabled:
|
||||
raise ValueError("A2A protocol is not enabled for this agent")
|
||||
|
||||
if not self._a2a_integration:
|
||||
self._a2a_integration = A2AAgentIntegration()
|
||||
|
||||
url = agent_url or self.a2a_url
|
||||
if not url:
|
||||
raise ValueError("No A2A agent URL provided")
|
||||
|
||||
try:
|
||||
import asyncio
|
||||
if asyncio.get_event_loop().is_running():
|
||||
return await self._a2a_integration.execute_task_via_a2a(
|
||||
agent_url=url,
|
||||
task_description=task_description,
|
||||
context=context,
|
||||
api_key=api_key,
|
||||
timeout=timeout,
|
||||
)
|
||||
else:
|
||||
return asyncio.run(self._a2a_integration.execute_task_via_a2a(
|
||||
agent_url=url,
|
||||
task_description=task_description,
|
||||
context=context,
|
||||
api_key=api_key,
|
||||
timeout=timeout,
|
||||
))
|
||||
except Exception as e:
|
||||
self._logger.exception(f"Error executing task via A2A: {e}")
|
||||
raise
|
||||
|
||||
async def handle_a2a_task(
|
||||
self,
|
||||
task_id: str,
|
||||
task_description: str,
|
||||
context: Optional[str] = None,
|
||||
) -> str:
|
||||
"""Handle an A2A task.
|
||||
|
||||
Args:
|
||||
task_id: The ID of the A2A task.
|
||||
task_description: The description of the task.
|
||||
context: Additional context for the task.
|
||||
|
||||
Returns:
|
||||
The result of the task execution.
|
||||
|
||||
Raises:
|
||||
ValueError: If A2A is not enabled.
|
||||
Exception: If there is an error handling the task.
|
||||
"""
|
||||
if not self.a2a_enabled:
|
||||
raise ValueError("A2A protocol is not enabled for this agent")
|
||||
|
||||
if not self._a2a_integration:
|
||||
self._a2a_integration = A2AAgentIntegration()
|
||||
|
||||
# Create a Task object from the task description
|
||||
task = Task(
|
||||
description=task_description,
|
||||
agent=self,
|
||||
expected_output="text", # Default to text output
|
||||
)
|
||||
|
||||
try:
|
||||
result = self.execute_task(task=task, context=context)
|
||||
return result
|
||||
except Exception as e:
|
||||
self._logger.exception(f"Error handling A2A task: {e}")
|
||||
raise
|
||||
|
||||
def create_agent_executor(
|
||||
self, tools: Optional[List[BaseTool]] = None, task=None
|
||||
|
||||
@@ -107,12 +107,6 @@ class BaseAgent(ABC, BaseModel):
|
||||
default=False,
|
||||
description="Enable agent to delegate and ask questions among each other.",
|
||||
)
|
||||
allowed_agents: Optional[List[str]] = Field(
|
||||
default=None,
|
||||
description="List of agent roles that this agent is allowed to delegate tasks to. "
|
||||
"If None, delegation is unrestricted when allow_delegation is True.",
|
||||
examples=["Researcher", "Analyst"]
|
||||
)
|
||||
tools: Optional[List[Any]] = Field(
|
||||
default_factory=list, description="Tools at agents' disposal"
|
||||
)
|
||||
@@ -142,17 +136,6 @@ class BaseAgent(ABC, BaseModel):
|
||||
def process_model_config(cls, values):
|
||||
return process_config(values, cls)
|
||||
|
||||
@field_validator("allowed_agents")
|
||||
@classmethod
|
||||
def validate_allowed_agents(cls, allowed_agents: Optional[List[str]]) -> Optional[List[str]]:
|
||||
"""Validate the allowed_agents parameter."""
|
||||
if allowed_agents is not None:
|
||||
if not isinstance(allowed_agents, list):
|
||||
raise ValueError("allowed_agents must be a list of strings")
|
||||
if not all(isinstance(agent, str) for agent in allowed_agents):
|
||||
raise ValueError("all entries in allowed_agents must be strings")
|
||||
return allowed_agents
|
||||
|
||||
@field_validator("tools")
|
||||
@classmethod
|
||||
def validate_tools(cls, tools: List[Any]) -> List[BaseTool]:
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
"""Exceptions for CrewAI."""
|
||||
|
||||
class AgentLookupError(Exception):
|
||||
"""Exception raised when an agent cannot be found."""
|
||||
pass
|
||||
|
||||
|
||||
class UnauthorizedDelegationError(Exception):
|
||||
"""Exception raised when an agent attempts unauthorized delegation."""
|
||||
pass
|
||||
@@ -3,14 +3,12 @@ from typing import Optional, Union
|
||||
from pydantic import Field
|
||||
|
||||
from crewai.agents.agent_builder.base_agent import BaseAgent
|
||||
from crewai.exceptions import AgentLookupError, UnauthorizedDelegationError
|
||||
from crewai.task import Task
|
||||
from crewai.tools.base_tool import BaseTool
|
||||
from crewai.utilities import I18N
|
||||
from crewai.utilities.agent_lookup import AgentLookupMixin
|
||||
|
||||
|
||||
class BaseAgentTool(BaseTool, AgentLookupMixin):
|
||||
class BaseAgentTool(BaseTool):
|
||||
"""Base class for agent-related tools"""
|
||||
|
||||
agents: list[BaseAgent] = Field(description="List of available agents")
|
||||
@@ -26,21 +24,6 @@ class BaseAgentTool(BaseTool, AgentLookupMixin):
|
||||
coworker = coworker[1:-1].split(",")[0]
|
||||
return coworker
|
||||
|
||||
def can_delegate_to(self, delegating_agent: BaseAgent, target_agent: BaseAgent) -> bool:
|
||||
"""Check if an agent can delegate to another agent.
|
||||
|
||||
Args:
|
||||
delegating_agent: The agent attempting to delegate
|
||||
target_agent: The agent being delegated to
|
||||
|
||||
Returns:
|
||||
bool: True if delegation is allowed, False otherwise
|
||||
"""
|
||||
return (delegating_agent.allow_delegation and
|
||||
(delegating_agent.allowed_agents is None or
|
||||
(len(delegating_agent.allowed_agents) > 0 and
|
||||
target_agent.role in delegating_agent.allowed_agents)))
|
||||
|
||||
def _execute(
|
||||
self, agent_name: Union[str, None], task: str, context: Union[str, None]
|
||||
) -> str:
|
||||
@@ -48,38 +31,38 @@ class BaseAgentTool(BaseTool, AgentLookupMixin):
|
||||
if agent_name is None:
|
||||
agent_name = ""
|
||||
|
||||
target_agent = self.get_agent_by_role(agent_name, self.agents)
|
||||
if not target_agent:
|
||||
raise AgentLookupError(
|
||||
f"Agent with role '{agent_name}' not found. Available agents: "
|
||||
f"{', '.join(agent.role for agent in self.agents)}"
|
||||
)
|
||||
delegating_agent = next(
|
||||
(agent for agent in self.agents if agent.allow_delegation), None
|
||||
)
|
||||
|
||||
if delegating_agent and not self.can_delegate_to(delegating_agent, target_agent):
|
||||
raise UnauthorizedDelegationError(
|
||||
f"Agent '{delegating_agent.role}' cannot delegate to '{target_agent.role}'. "
|
||||
f"Allowed targets: {', '.join(delegating_agent.allowed_agents or [])}"
|
||||
)
|
||||
|
||||
task_with_assigned_agent = Task(
|
||||
description=task,
|
||||
agent=target_agent,
|
||||
expected_output=target_agent.i18n.slice("manager_request"),
|
||||
i18n=target_agent.i18n,
|
||||
)
|
||||
return target_agent.execute_task(task_with_assigned_agent, context)
|
||||
except AgentLookupError as e:
|
||||
# It is important to remove the quotes from the agent name.
|
||||
# The reason we have to do this is because less-powerful LLM's
|
||||
# have difficulty producing valid JSON.
|
||||
# As a result, we end up with invalid JSON that is truncated like this:
|
||||
# {"task": "....", "coworker": "....
|
||||
# when it should look like this:
|
||||
# {"task": "....", "coworker": "...."}
|
||||
agent_name = agent_name.casefold().replace('"', "").replace("\n", "")
|
||||
agent = [ # type: ignore # Incompatible types in assignment (expression has type "list[BaseAgent]", variable has type "str | None")
|
||||
available_agent
|
||||
for available_agent in self.agents
|
||||
if available_agent.role.casefold().replace("\n", "") == agent_name
|
||||
]
|
||||
except Exception as _:
|
||||
return self.i18n.errors("agent_tool_unexisting_coworker").format(
|
||||
coworkers="\n".join(f"- {agent.role}" for agent in self.agents)
|
||||
coworkers="\n".join(
|
||||
[f"- {agent.role.casefold()}" for agent in self.agents]
|
||||
)
|
||||
)
|
||||
except UnauthorizedDelegationError as e:
|
||||
return self.i18n.errors("agent_tool_unauthorized_delegation").format(
|
||||
agent=delegating_agent.role,
|
||||
target=target_agent.role,
|
||||
allowed="\n".join(f"- {role}" for role in (delegating_agent.allowed_agents or []))
|
||||
|
||||
if not agent:
|
||||
return self.i18n.errors("agent_tool_unexisting_coworker").format(
|
||||
coworkers="\n".join(
|
||||
[f"- {agent.role.casefold()}" for agent in self.agents]
|
||||
)
|
||||
)
|
||||
except Exception as e:
|
||||
return self.i18n.errors("tool_usage_error").format(error=str(e))
|
||||
|
||||
agent = agent[0]
|
||||
task_with_assigned_agent = Task( # type: ignore # Incompatible types in assignment (expression has type "Task", variable has type "str")
|
||||
description=task,
|
||||
agent=agent,
|
||||
expected_output=agent.i18n.slice("manager_request"),
|
||||
i18n=agent.i18n,
|
||||
)
|
||||
return agent.execute_task(task_with_assigned_agent, context)
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
"force_final_answer_error": "You can't keep going, this was the best you could do.\n {formatted_answer.text}",
|
||||
"force_final_answer": "Now it's time you MUST give your absolute best final answer. You'll ignore all previous instructions, stop using any tools, and just return your absolute BEST Final answer.",
|
||||
"agent_tool_unexisting_coworker": "\nError executing tool. coworker mentioned not found, it must be one of the following options:\n{coworkers}\n",
|
||||
"agent_tool_unauthorized_delegation": "\nAuthorization Error: Agent '{agent}' cannot delegate to '{target}'.\nAllowed delegation targets:\n{allowed}\nPlease check agent configuration or contact administrator.\n",
|
||||
"task_repeated_usage": "I tried reusing the same input, I must stop using this action input. I'll try something else instead.\n\n",
|
||||
"tool_usage_error": "I encountered an error: {error}",
|
||||
"tool_arguments_error": "Error: the Action Input is not a valid key, value dictionary.",
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
"""Type definitions for CrewAI."""
|
||||
|
||||
469
src/crewai/types/a2a.py
Normal file
469
src/crewai/types/a2a.py
Normal file
@@ -0,0 +1,469 @@
|
||||
"""
|
||||
A2A protocol types for CrewAI.
|
||||
|
||||
This module implements the A2A (Agent-to-Agent) protocol types as defined by Google.
|
||||
The A2A protocol enables interoperability between different agent systems.
|
||||
|
||||
For more information, see: https://developers.googleblog.com/en/a2a-a-new-era-of-agent-interoperability/
|
||||
"""
|
||||
|
||||
from datetime import datetime
|
||||
from enum import Enum
|
||||
from typing import Annotated, Any, Dict, List, Literal, Optional, Self, Union
|
||||
from uuid import uuid4
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, Field, TypeAdapter, field_serializer, model_validator
|
||||
|
||||
|
||||
class TaskState(str, Enum):
|
||||
"""Task state in the A2A protocol."""
|
||||
SUBMITTED = 'submitted'
|
||||
WORKING = 'working'
|
||||
INPUT_REQUIRED = 'input-required'
|
||||
COMPLETED = 'completed'
|
||||
CANCELED = 'canceled'
|
||||
FAILED = 'failed'
|
||||
UNKNOWN = 'unknown'
|
||||
EXPIRED = 'expired'
|
||||
|
||||
@classmethod
|
||||
def valid_transitions(cls) -> Dict[str, List[str]]:
|
||||
"""Get valid state transitions.
|
||||
|
||||
Returns:
|
||||
A dictionary mapping from state to list of valid next states.
|
||||
"""
|
||||
return {
|
||||
cls.SUBMITTED: [cls.WORKING, cls.CANCELED, cls.FAILED],
|
||||
cls.WORKING: [cls.INPUT_REQUIRED, cls.COMPLETED, cls.CANCELED, cls.FAILED],
|
||||
cls.INPUT_REQUIRED: [cls.WORKING, cls.CANCELED, cls.FAILED],
|
||||
cls.COMPLETED: [], # Terminal state
|
||||
cls.CANCELED: [], # Terminal state
|
||||
cls.FAILED: [], # Terminal state
|
||||
cls.UNKNOWN: [cls.SUBMITTED, cls.WORKING, cls.INPUT_REQUIRED, cls.COMPLETED, cls.CANCELED, cls.FAILED],
|
||||
cls.EXPIRED: [], # Terminal state
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def is_valid_transition(cls, from_state: 'TaskState', to_state: 'TaskState') -> bool:
|
||||
"""Check if a state transition is valid.
|
||||
|
||||
Args:
|
||||
from_state: The current state.
|
||||
to_state: The target state.
|
||||
|
||||
Returns:
|
||||
True if the transition is valid, False otherwise.
|
||||
"""
|
||||
if from_state == to_state:
|
||||
return True
|
||||
|
||||
valid_next_states = cls.valid_transitions().get(from_state, [])
|
||||
return to_state in valid_next_states
|
||||
|
||||
|
||||
class TextPart(BaseModel):
|
||||
"""Text part in the A2A protocol."""
|
||||
type: Literal['text'] = 'text'
|
||||
text: str
|
||||
metadata: Optional[Dict[str, Any]] = None
|
||||
|
||||
|
||||
class FileContent(BaseModel):
|
||||
"""File content in the A2A protocol."""
|
||||
name: Optional[str] = None
|
||||
mimeType: Optional[str] = None
|
||||
bytes: Optional[str] = None
|
||||
uri: Optional[str] = None
|
||||
|
||||
@model_validator(mode='after')
|
||||
def check_content(self) -> Self:
|
||||
"""Validate file content has either bytes or uri."""
|
||||
if not (self.bytes or self.uri):
|
||||
raise ValueError(
|
||||
"Either 'bytes' or 'uri' must be present in the file data"
|
||||
)
|
||||
if self.bytes and self.uri:
|
||||
raise ValueError(
|
||||
"Only one of 'bytes' or 'uri' can be present in the file data"
|
||||
)
|
||||
return self
|
||||
|
||||
|
||||
class FilePart(BaseModel):
|
||||
"""File part in the A2A protocol."""
|
||||
type: Literal['file'] = 'file'
|
||||
file: FileContent
|
||||
metadata: Optional[Dict[str, Any]] = None
|
||||
|
||||
|
||||
class DataPart(BaseModel):
|
||||
"""Data part in the A2A protocol."""
|
||||
type: Literal['data'] = 'data'
|
||||
data: Dict[str, Any]
|
||||
metadata: Optional[Dict[str, Any]] = None
|
||||
|
||||
|
||||
Part = Annotated[Union[TextPart, FilePart, DataPart], Field(discriminator='type')]
|
||||
|
||||
|
||||
class Message(BaseModel):
|
||||
"""Message in the A2A protocol."""
|
||||
role: Literal['user', 'agent']
|
||||
parts: List[Part]
|
||||
metadata: Optional[Dict[str, Any]] = None
|
||||
|
||||
|
||||
class TaskStatus(BaseModel):
|
||||
"""Task status in the A2A protocol."""
|
||||
state: TaskState
|
||||
message: Optional[Message] = None
|
||||
timestamp: datetime = Field(default_factory=datetime.now)
|
||||
previous_state: Optional[TaskState] = None
|
||||
|
||||
@field_serializer('timestamp')
|
||||
def serialize_dt(self, dt: datetime, _info):
|
||||
"""Serialize datetime to ISO format."""
|
||||
return dt.isoformat()
|
||||
|
||||
@model_validator(mode='after')
|
||||
def validate_state_transition(self) -> Self:
|
||||
"""Validate state transition."""
|
||||
if self.previous_state and not TaskState.is_valid_transition(self.previous_state, self.state):
|
||||
raise ValueError(
|
||||
f"Invalid state transition from {self.previous_state} to {self.state}"
|
||||
)
|
||||
return self
|
||||
|
||||
|
||||
class Artifact(BaseModel):
|
||||
"""Artifact in the A2A protocol."""
|
||||
name: Optional[str] = None
|
||||
description: Optional[str] = None
|
||||
parts: List[Part]
|
||||
metadata: Optional[Dict[str, Any]] = None
|
||||
index: int = 0
|
||||
append: Optional[bool] = None
|
||||
lastChunk: Optional[bool] = None
|
||||
|
||||
|
||||
class Task(BaseModel):
|
||||
"""Task in the A2A protocol."""
|
||||
id: str
|
||||
sessionId: Optional[str] = None
|
||||
status: TaskStatus
|
||||
artifacts: Optional[List[Artifact]] = None
|
||||
history: Optional[List[Message]] = None
|
||||
metadata: Optional[Dict[str, Any]] = None
|
||||
|
||||
|
||||
class TaskStatusUpdateEvent(BaseModel):
|
||||
"""Task status update event in the A2A protocol."""
|
||||
id: str
|
||||
status: TaskStatus
|
||||
final: bool = False
|
||||
metadata: Optional[Dict[str, Any]] = None
|
||||
|
||||
|
||||
class TaskArtifactUpdateEvent(BaseModel):
|
||||
"""Task artifact update event in the A2A protocol."""
|
||||
id: str
|
||||
artifact: Artifact
|
||||
metadata: Optional[Dict[str, Any]] = None
|
||||
|
||||
|
||||
class AuthenticationInfo(BaseModel):
|
||||
"""Authentication information in the A2A protocol."""
|
||||
model_config = ConfigDict(extra='allow')
|
||||
|
||||
schemes: List[str]
|
||||
credentials: Optional[str] = None
|
||||
|
||||
|
||||
class PushNotificationConfig(BaseModel):
|
||||
"""Push notification configuration in the A2A protocol."""
|
||||
url: str
|
||||
token: Optional[str] = None
|
||||
authentication: Optional[AuthenticationInfo] = None
|
||||
|
||||
|
||||
class TaskIdParams(BaseModel):
|
||||
"""Task ID parameters in the A2A protocol."""
|
||||
id: str
|
||||
metadata: Optional[Dict[str, Any]] = None
|
||||
|
||||
|
||||
class TaskQueryParams(TaskIdParams):
|
||||
"""Task query parameters in the A2A protocol."""
|
||||
historyLength: Optional[int] = None
|
||||
|
||||
|
||||
class TaskSendParams(BaseModel):
|
||||
"""Task send parameters in the A2A protocol."""
|
||||
id: str
|
||||
sessionId: str = Field(default_factory=lambda: uuid4().hex)
|
||||
message: Message
|
||||
acceptedOutputModes: Optional[List[str]] = None
|
||||
pushNotification: Optional[PushNotificationConfig] = None
|
||||
historyLength: Optional[int] = None
|
||||
metadata: Optional[Dict[str, Any]] = None
|
||||
|
||||
|
||||
class TaskPushNotificationConfig(BaseModel):
|
||||
"""Task push notification configuration in the A2A protocol."""
|
||||
id: str
|
||||
pushNotificationConfig: PushNotificationConfig
|
||||
|
||||
|
||||
|
||||
class JSONRPCMessage(BaseModel):
|
||||
"""JSON-RPC message in the A2A protocol."""
|
||||
jsonrpc: Literal['2.0'] = '2.0'
|
||||
id: Optional[Union[int, str]] = Field(default_factory=lambda: uuid4().hex)
|
||||
|
||||
|
||||
class JSONRPCRequest(JSONRPCMessage):
|
||||
"""JSON-RPC request in the A2A protocol."""
|
||||
method: str
|
||||
params: Optional[Dict[str, Any]] = None
|
||||
|
||||
|
||||
class JSONRPCError(BaseModel):
|
||||
"""JSON-RPC error in the A2A protocol."""
|
||||
code: int
|
||||
message: str
|
||||
data: Optional[Any] = None
|
||||
|
||||
|
||||
class JSONRPCResponse(JSONRPCMessage):
|
||||
"""JSON-RPC response in the A2A protocol."""
|
||||
result: Optional[Any] = None
|
||||
error: Optional[JSONRPCError] = None
|
||||
|
||||
|
||||
class SendTaskRequest(JSONRPCRequest):
|
||||
"""Send task request in the A2A protocol."""
|
||||
method: Literal['tasks/send'] = 'tasks/send'
|
||||
params: TaskSendParams
|
||||
|
||||
|
||||
class SendTaskResponse(JSONRPCResponse):
|
||||
"""Send task response in the A2A protocol."""
|
||||
result: Optional[Task] = None
|
||||
|
||||
|
||||
class SendTaskStreamingRequest(JSONRPCRequest):
|
||||
"""Send task streaming request in the A2A protocol."""
|
||||
method: Literal['tasks/sendSubscribe'] = 'tasks/sendSubscribe'
|
||||
params: TaskSendParams
|
||||
|
||||
|
||||
class SendTaskStreamingResponse(JSONRPCResponse):
|
||||
"""Send task streaming response in the A2A protocol."""
|
||||
result: Optional[Union[TaskStatusUpdateEvent, TaskArtifactUpdateEvent]] = None
|
||||
|
||||
|
||||
class GetTaskRequest(JSONRPCRequest):
|
||||
"""Get task request in the A2A protocol."""
|
||||
method: Literal['tasks/get'] = 'tasks/get'
|
||||
params: TaskQueryParams
|
||||
|
||||
|
||||
class GetTaskResponse(JSONRPCResponse):
|
||||
"""Get task response in the A2A protocol."""
|
||||
result: Optional[Task] = None
|
||||
|
||||
|
||||
class CancelTaskRequest(JSONRPCRequest):
|
||||
"""Cancel task request in the A2A protocol."""
|
||||
method: Literal['tasks/cancel'] = 'tasks/cancel'
|
||||
params: TaskIdParams
|
||||
|
||||
|
||||
class CancelTaskResponse(JSONRPCResponse):
|
||||
"""Cancel task response in the A2A protocol."""
|
||||
result: Optional[Task] = None
|
||||
|
||||
|
||||
class SetTaskPushNotificationRequest(JSONRPCRequest):
|
||||
"""Set task push notification request in the A2A protocol."""
|
||||
method: Literal['tasks/pushNotification/set'] = 'tasks/pushNotification/set'
|
||||
params: TaskPushNotificationConfig
|
||||
|
||||
|
||||
class SetTaskPushNotificationResponse(JSONRPCResponse):
|
||||
"""Set task push notification response in the A2A protocol."""
|
||||
result: Optional[TaskPushNotificationConfig] = None
|
||||
|
||||
|
||||
class GetTaskPushNotificationRequest(JSONRPCRequest):
|
||||
"""Get task push notification request in the A2A protocol."""
|
||||
method: Literal['tasks/pushNotification/get'] = 'tasks/pushNotification/get'
|
||||
params: TaskIdParams
|
||||
|
||||
|
||||
class GetTaskPushNotificationResponse(JSONRPCResponse):
|
||||
"""Get task push notification response in the A2A protocol."""
|
||||
result: Optional[TaskPushNotificationConfig] = None
|
||||
|
||||
|
||||
class TaskResubscriptionRequest(JSONRPCRequest):
|
||||
"""Task resubscription request in the A2A protocol."""
|
||||
method: Literal['tasks/resubscribe'] = 'tasks/resubscribe'
|
||||
params: TaskIdParams
|
||||
|
||||
|
||||
A2ARequest = TypeAdapter(
|
||||
Annotated[
|
||||
Union[
|
||||
SendTaskRequest,
|
||||
GetTaskRequest,
|
||||
CancelTaskRequest,
|
||||
SetTaskPushNotificationRequest,
|
||||
GetTaskPushNotificationRequest,
|
||||
TaskResubscriptionRequest,
|
||||
SendTaskStreamingRequest,
|
||||
],
|
||||
Field(discriminator='method'),
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
class JSONParseError(JSONRPCError):
|
||||
"""JSON parse error in the A2A protocol."""
|
||||
code: int = -32700
|
||||
message: str = 'Invalid JSON payload'
|
||||
data: Optional[Any] = None
|
||||
|
||||
|
||||
class InvalidRequestError(JSONRPCError):
|
||||
"""Invalid request error in the A2A protocol."""
|
||||
code: int = -32600
|
||||
message: str = 'Request payload validation error'
|
||||
data: Optional[Any] = None
|
||||
|
||||
|
||||
class MethodNotFoundError(JSONRPCError):
|
||||
"""Method not found error in the A2A protocol."""
|
||||
code: int = -32601
|
||||
message: str = 'Method not found'
|
||||
data: None = None
|
||||
|
||||
|
||||
class InvalidParamsError(JSONRPCError):
|
||||
"""Invalid parameters error in the A2A protocol."""
|
||||
code: int = -32602
|
||||
message: str = 'Invalid parameters'
|
||||
data: Optional[Any] = None
|
||||
|
||||
|
||||
class InternalError(JSONRPCError):
|
||||
"""Internal error in the A2A protocol."""
|
||||
code: int = -32603
|
||||
message: str = 'Internal error'
|
||||
data: Optional[Any] = None
|
||||
|
||||
|
||||
class TaskNotFoundError(JSONRPCError):
|
||||
"""Task not found error in the A2A protocol."""
|
||||
code: int = -32001
|
||||
message: str = 'Task not found'
|
||||
data: None = None
|
||||
|
||||
|
||||
class TaskNotCancelableError(JSONRPCError):
|
||||
"""Task not cancelable error in the A2A protocol."""
|
||||
code: int = -32002
|
||||
message: str = 'Task cannot be canceled'
|
||||
data: None = None
|
||||
|
||||
|
||||
class PushNotificationNotSupportedError(JSONRPCError):
|
||||
"""Push notification not supported error in the A2A protocol."""
|
||||
code: int = -32003
|
||||
message: str = 'Push Notification is not supported'
|
||||
data: None = None
|
||||
|
||||
|
||||
class UnsupportedOperationError(JSONRPCError):
|
||||
"""Unsupported operation error in the A2A protocol."""
|
||||
code: int = -32004
|
||||
message: str = 'This operation is not supported'
|
||||
data: None = None
|
||||
|
||||
|
||||
class ContentTypeNotSupportedError(JSONRPCError):
|
||||
"""Content type not supported error in the A2A protocol."""
|
||||
code: int = -32005
|
||||
message: str = 'Incompatible content types'
|
||||
data: None = None
|
||||
|
||||
|
||||
class AgentProvider(BaseModel):
|
||||
"""Agent provider in the A2A protocol."""
|
||||
organization: str
|
||||
url: Optional[str] = None
|
||||
|
||||
|
||||
class AgentCapabilities(BaseModel):
|
||||
"""Agent capabilities in the A2A protocol."""
|
||||
streaming: bool = False
|
||||
pushNotifications: bool = False
|
||||
stateTransitionHistory: bool = False
|
||||
|
||||
|
||||
class AgentAuthentication(BaseModel):
|
||||
"""Agent authentication in the A2A protocol."""
|
||||
schemes: List[str]
|
||||
credentials: Optional[str] = None
|
||||
|
||||
|
||||
class AgentSkill(BaseModel):
|
||||
"""Agent skill in the A2A protocol."""
|
||||
id: str
|
||||
name: str
|
||||
description: Optional[str] = None
|
||||
tags: Optional[List[str]] = None
|
||||
examples: Optional[List[str]] = None
|
||||
inputModes: Optional[List[str]] = None
|
||||
outputModes: Optional[List[str]] = None
|
||||
|
||||
|
||||
class AgentCard(BaseModel):
|
||||
"""Agent card in the A2A protocol."""
|
||||
name: str
|
||||
description: Optional[str] = None
|
||||
url: str
|
||||
provider: Optional[AgentProvider] = None
|
||||
version: str
|
||||
documentationUrl: Optional[str] = None
|
||||
capabilities: AgentCapabilities
|
||||
authentication: Optional[AgentAuthentication] = None
|
||||
defaultInputModes: List[str] = ['text']
|
||||
defaultOutputModes: List[str] = ['text']
|
||||
skills: List[AgentSkill]
|
||||
|
||||
|
||||
class A2AClientError(Exception):
|
||||
"""Base exception for A2A client errors."""
|
||||
pass
|
||||
|
||||
|
||||
class A2AClientHTTPError(A2AClientError):
|
||||
"""HTTP error in the A2A client."""
|
||||
def __init__(self, status_code: int, message: str):
|
||||
self.status_code = status_code
|
||||
self.message = message
|
||||
super().__init__(f'HTTP Error {status_code}: {message}')
|
||||
|
||||
|
||||
class A2AClientJSONError(A2AClientError):
|
||||
"""JSON error in the A2A client."""
|
||||
def __init__(self, message: str):
|
||||
self.message = message
|
||||
super().__init__(f'JSON Error: {message}')
|
||||
|
||||
|
||||
class MissingAPIKeyError(Exception):
|
||||
"""Exception for missing API key."""
|
||||
pass
|
||||
@@ -1,26 +0,0 @@
|
||||
"""Agent lookup utilities for CrewAI."""
|
||||
|
||||
from typing import List, Optional, Union
|
||||
from ..agents.agent_builder.base_agent import BaseAgent
|
||||
from ..exceptions import AgentLookupError
|
||||
|
||||
|
||||
class AgentLookupMixin:
|
||||
"""Mixin class for agent lookup functionality."""
|
||||
|
||||
def get_agent_by_role(self, role: str, agents: List[BaseAgent]) -> Union[BaseAgent, None]:
|
||||
"""Find an agent by role, case-insensitive.
|
||||
|
||||
Args:
|
||||
role: The role to search for
|
||||
agents: List of agents to search through
|
||||
|
||||
Returns:
|
||||
The found agent or None
|
||||
"""
|
||||
normalized_role = role.casefold().replace('"', "").replace("\n", "")
|
||||
return next(
|
||||
(agent for agent in agents
|
||||
if agent.role.casefold().replace("\n", "") == normalized_role),
|
||||
None
|
||||
)
|
||||
1
tests/a2a/__init__.py
Normal file
1
tests/a2a/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
"""Tests for the A2A protocol implementation."""
|
||||
240
tests/a2a/test_a2a_integration.py
Normal file
240
tests/a2a/test_a2a_integration.py
Normal file
@@ -0,0 +1,240 @@
|
||||
"""Tests for the A2A protocol integration."""
|
||||
|
||||
import asyncio
|
||||
from datetime import datetime
|
||||
import pytest
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
||||
pytestmark = pytest.mark.asyncio
|
||||
|
||||
from crewai.agent import Agent
|
||||
from crewai.a2a import A2AAgentIntegration, A2AClient, A2AServer, InMemoryTaskManager
|
||||
from crewai.task import Task
|
||||
from crewai.types.a2a import (
|
||||
JSONRPCResponse,
|
||||
Message,
|
||||
Task as A2ATask,
|
||||
TaskState,
|
||||
TaskStatus,
|
||||
TaskStatusUpdateEvent,
|
||||
TextPart,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def agent():
|
||||
"""Create an agent with A2A enabled."""
|
||||
return Agent(
|
||||
role="test_agent",
|
||||
goal="Test A2A protocol",
|
||||
backstory="I am a test agent",
|
||||
a2a_enabled=True,
|
||||
a2a_url="http://localhost:8000",
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def task():
|
||||
"""Create a task."""
|
||||
return Task(
|
||||
description="Test task",
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def a2a_task():
|
||||
"""Create an A2A task."""
|
||||
return A2ATask(
|
||||
id="test_task_id",
|
||||
history=[
|
||||
Message(
|
||||
role="user",
|
||||
parts=[TextPart(text="Test task description")],
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def a2a_integration():
|
||||
"""Create an A2A integration."""
|
||||
return A2AAgentIntegration()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def a2a_client():
|
||||
"""Create an A2A client."""
|
||||
return A2AClient(base_url="http://localhost:8000", api_key="test_api_key")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def task_manager():
|
||||
"""Create a task manager."""
|
||||
return InMemoryTaskManager()
|
||||
|
||||
|
||||
class TestA2AIntegration:
|
||||
"""Tests for the A2A protocol integration."""
|
||||
|
||||
def test_agent_a2a_attributes(self, agent):
|
||||
"""Test that the agent has A2A attributes."""
|
||||
assert agent.a2a_enabled is True
|
||||
assert agent.a2a_url == "http://localhost:8000"
|
||||
assert agent._a2a_integration is not None
|
||||
|
||||
@patch("crewai.a2a.agent.A2AAgentIntegration.execute_task_via_a2a")
|
||||
def test_execute_task_via_a2a(self, mock_execute, agent):
|
||||
"""Test executing a task via A2A."""
|
||||
mock_execute.return_value = "Task result"
|
||||
|
||||
result = asyncio.run(
|
||||
agent.execute_task_via_a2a(
|
||||
task_description="Test task",
|
||||
context="Test context",
|
||||
)
|
||||
)
|
||||
|
||||
assert result == "Task result"
|
||||
mock_execute.assert_called_once_with(
|
||||
agent_url="http://localhost:8000",
|
||||
task_description="Test task",
|
||||
context="Test context",
|
||||
api_key=None,
|
||||
timeout=300,
|
||||
)
|
||||
|
||||
@patch("crewai.agent.Agent.execute_task")
|
||||
def test_handle_a2a_task(self, mock_execute, agent):
|
||||
"""Test handling an A2A task."""
|
||||
mock_execute.return_value = "Task result"
|
||||
|
||||
result = asyncio.run(
|
||||
agent.handle_a2a_task(
|
||||
task_id="test_task_id",
|
||||
task_description="Test task",
|
||||
context="Test context",
|
||||
)
|
||||
)
|
||||
|
||||
assert result == "Task result"
|
||||
mock_execute.assert_called_once()
|
||||
args, kwargs = mock_execute.call_args
|
||||
assert kwargs["context"] == "Test context"
|
||||
assert kwargs["task"].description == "Test task"
|
||||
|
||||
def test_a2a_disabled(self, agent):
|
||||
"""Test that A2A methods raise ValueError when A2A is disabled."""
|
||||
agent.a2a_enabled = False
|
||||
|
||||
with pytest.raises(ValueError, match="A2A protocol is not enabled for this agent"):
|
||||
asyncio.run(
|
||||
agent.execute_task_via_a2a(
|
||||
task_description="Test task",
|
||||
)
|
||||
)
|
||||
|
||||
with pytest.raises(ValueError, match="A2A protocol is not enabled for this agent"):
|
||||
asyncio.run(
|
||||
agent.handle_a2a_task(
|
||||
task_id="test_task_id",
|
||||
task_description="Test task",
|
||||
)
|
||||
)
|
||||
|
||||
def test_no_agent_url(self, agent):
|
||||
"""Test that execute_task_via_a2a raises ValueError when no agent URL is provided."""
|
||||
agent.a2a_url = None
|
||||
|
||||
with pytest.raises(ValueError, match="No A2A agent URL provided"):
|
||||
asyncio.run(
|
||||
agent.execute_task_via_a2a(
|
||||
task_description="Test task",
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class TestA2AAgentIntegration:
|
||||
"""Tests for the A2AAgentIntegration class."""
|
||||
|
||||
@patch("crewai.a2a.client.A2AClient.send_task_streaming")
|
||||
async def test_execute_task_via_a2a(self, mock_send_task, a2a_integration):
|
||||
"""Test executing a task via A2A."""
|
||||
queue = asyncio.Queue()
|
||||
await queue.put(
|
||||
TaskStatusUpdateEvent(
|
||||
id="test_task_id",
|
||||
status=TaskStatus(
|
||||
state=TaskState.COMPLETED,
|
||||
message=Message(
|
||||
role="agent",
|
||||
parts=[TextPart(text="Task result")],
|
||||
),
|
||||
),
|
||||
final=True,
|
||||
)
|
||||
)
|
||||
|
||||
mock_send_task.return_value = queue
|
||||
|
||||
result = await a2a_integration.execute_task_via_a2a(
|
||||
agent_url="http://localhost:8000",
|
||||
task_description="Test task",
|
||||
context="Test context",
|
||||
)
|
||||
|
||||
assert result == "Task result"
|
||||
mock_send_task.assert_called_once()
|
||||
|
||||
|
||||
class TestA2AServer:
|
||||
"""Tests for the A2AServer class."""
|
||||
|
||||
@patch("fastapi.FastAPI.post")
|
||||
def test_server_initialization(self, mock_post, task_manager):
|
||||
"""Test server initialization."""
|
||||
server = A2AServer(task_manager=task_manager)
|
||||
assert server.task_manager == task_manager
|
||||
assert server.app is not None
|
||||
assert mock_post.call_count == 4 # 4 endpoints registered
|
||||
|
||||
|
||||
class TestA2AClient:
|
||||
"""Tests for the A2AClient class."""
|
||||
|
||||
@patch("crewai.a2a.client.A2AClient._send_jsonrpc_request")
|
||||
async def test_send_task(self, mock_send_request, a2a_client):
|
||||
"""Test sending a task."""
|
||||
mock_response = JSONRPCResponse(
|
||||
jsonrpc="2.0",
|
||||
id="test_request_id",
|
||||
result=A2ATask(
|
||||
id="test_task_id",
|
||||
sessionId="test_session_id",
|
||||
status=TaskStatus(
|
||||
state=TaskState.SUBMITTED,
|
||||
timestamp=datetime.now(),
|
||||
),
|
||||
history=[
|
||||
Message(
|
||||
role="user",
|
||||
parts=[TextPart(text="Test task description")],
|
||||
)
|
||||
],
|
||||
)
|
||||
)
|
||||
|
||||
mock_send_request.return_value = mock_response
|
||||
|
||||
task = await a2a_client.send_task(
|
||||
task_id="test_task_id",
|
||||
message=Message(
|
||||
role="user",
|
||||
parts=[TextPart(text="Test task description")],
|
||||
),
|
||||
session_id="test_session_id",
|
||||
)
|
||||
|
||||
assert task.id == "test_task_id"
|
||||
assert task.history[0].role == "user"
|
||||
assert task.history[0].parts[0].text == "Test task description"
|
||||
mock_send_request.assert_called_once()
|
||||
@@ -1,87 +1,4 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: !!binary |
|
||||
CqcXCiQKIgoMc2VydmljZS5uYW1lEhIKEGNyZXdBSS10ZWxlbWV0cnkS/hYKEgoQY3Jld2FpLnRl
|
||||
bGVtZXRyeRJ5ChBuJJtOdNaB05mOW/p3915eEgj2tkAd3rZcASoQVG9vbCBVc2FnZSBFcnJvcjAB
|
||||
OYa7/URvKBUYQUpcFEVvKBUYShoKDmNyZXdhaV92ZXJzaW9uEggKBjAuODYuMEoPCgNsbG0SCAoG
|
||||
Z3B0LTRvegIYAYUBAAEAABLJBwoQifhX01E5i+5laGdALAlZBBIIBuGM1aN+OPgqDENyZXcgQ3Jl
|
||||
YXRlZDABORVGruBvKBUYQaipwOBvKBUYShoKDmNyZXdhaV92ZXJzaW9uEggKBjAuODYuMEoaCg5w
|
||||
eXRob25fdmVyc2lvbhIICgYzLjEyLjdKLgoIY3Jld19rZXkSIgogN2U2NjA4OTg5ODU5YTY3ZWVj
|
||||
ODhlZWY3ZmNlODUyMjVKMQoHY3Jld19pZBImCiRiOThiNWEwMC01YTI1LTQxMDctYjQwNS1hYmYz
|
||||
MjBhOGYzYThKHAoMY3Jld19wcm9jZXNzEgwKCnNlcXVlbnRpYWxKEQoLY3Jld19tZW1vcnkSAhAA
|
||||
ShoKFGNyZXdfbnVtYmVyX29mX3Rhc2tzEgIYAUobChVjcmV3X251bWJlcl9vZl9hZ2VudHMSAhgB
|
||||
SuQCCgtjcmV3X2FnZW50cxLUAgrRAlt7ImtleSI6ICIyMmFjZDYxMWU0NGVmNWZhYzA1YjUzM2Q3
|
||||
NWU4ODkzYiIsICJpZCI6ICJkNWIyMzM1YS0yMmIyLTQyZWEtYmYwNS03OTc3NmU3MmYzOTIiLCAi
|
||||
cm9sZSI6ICJEYXRhIFNjaWVudGlzdCIsICJ2ZXJib3NlPyI6IGZhbHNlLCAibWF4X2l0ZXIiOiAy
|
||||
MCwgIm1heF9ycG0iOiBudWxsLCAiZnVuY3Rpb25fY2FsbGluZ19sbG0iOiAiIiwgImxsbSI6ICJn
|
||||
cHQtNG8tbWluaSIsICJkZWxlZ2F0aW9uX2VuYWJsZWQ/IjogZmFsc2UsICJhbGxvd19jb2RlX2V4
|
||||
ZWN1dGlvbj8iOiBmYWxzZSwgIm1heF9yZXRyeV9saW1pdCI6IDIsICJ0b29sc19uYW1lcyI6IFsi
|
||||
Z2V0IGdyZWV0aW5ncyJdfV1KkgIKCmNyZXdfdGFza3MSgwIKgAJbeyJrZXkiOiAiYTI3N2IzNGIy
|
||||
YzE0NmYwYzU2YzVlMTM1NmU4ZjhhNTciLCAiaWQiOiAiMjJiZWMyMzEtY2QyMS00YzU4LTgyN2Ut
|
||||
MDU4MWE4ZjBjMTExIiwgImFzeW5jX2V4ZWN1dGlvbj8iOiBmYWxzZSwgImh1bWFuX2lucHV0PyI6
|
||||
IGZhbHNlLCAiYWdlbnRfcm9sZSI6ICJEYXRhIFNjaWVudGlzdCIsICJhZ2VudF9rZXkiOiAiMjJh
|
||||
Y2Q2MTFlNDRlZjVmYWMwNWI1MzNkNzVlODg5M2IiLCAidG9vbHNfbmFtZXMiOiBbImdldCBncmVl
|
||||
dGluZ3MiXX1degIYAYUBAAEAABKOAgoQ5WYoxRtTyPjge4BduhL0rRIIv2U6rvWALfwqDFRhc2sg
|
||||
Q3JlYXRlZDABOX068uBvKBUYQZkv8+BvKBUYSi4KCGNyZXdfa2V5EiIKIDdlNjYwODk4OTg1OWE2
|
||||
N2VlYzg4ZWVmN2ZjZTg1MjI1SjEKB2NyZXdfaWQSJgokYjk4YjVhMDAtNWEyNS00MTA3LWI0MDUt
|
||||
YWJmMzIwYThmM2E4Si4KCHRhc2tfa2V5EiIKIGEyNzdiMzRiMmMxNDZmMGM1NmM1ZTEzNTZlOGY4
|
||||
YTU3SjEKB3Rhc2tfaWQSJgokMjJiZWMyMzEtY2QyMS00YzU4LTgyN2UtMDU4MWE4ZjBjMTExegIY
|
||||
AYUBAAEAABKQAQoQXyeDtJDFnyp2Fjk9YEGTpxIIaNE7gbhPNYcqClRvb2wgVXNhZ2UwATkaXTvj
|
||||
bygVGEGvx0rjbygVGEoaCg5jcmV3YWlfdmVyc2lvbhIICgYwLjg2LjBKHAoJdG9vbF9uYW1lEg8K
|
||||
DUdldCBHcmVldGluZ3NKDgoIYXR0ZW1wdHMSAhgBegIYAYUBAAEAABLVBwoQMWfznt0qwauEzl7T
|
||||
UOQxRBII9q+pUS5EdLAqDENyZXcgQ3JlYXRlZDABORONPORvKBUYQSAoS+RvKBUYShoKDmNyZXdh
|
||||
aV92ZXJzaW9uEggKBjAuODYuMEoaCg5weXRob25fdmVyc2lvbhIICgYzLjEyLjdKLgoIY3Jld19r
|
||||
ZXkSIgogYzMwNzYwMDkzMjY3NjE0NDRkNTdjNzFkMWRhM2YyN2NKMQoHY3Jld19pZBImCiQ3OTQw
|
||||
MTkyNS1iOGU5LTQ3MDgtODUzMC00NDhhZmEzYmY4YjBKHAoMY3Jld19wcm9jZXNzEgwKCnNlcXVl
|
||||
bnRpYWxKEQoLY3Jld19tZW1vcnkSAhAAShoKFGNyZXdfbnVtYmVyX29mX3Rhc2tzEgIYAUobChVj
|
||||
cmV3X251bWJlcl9vZl9hZ2VudHMSAhgBSuoCCgtjcmV3X2FnZW50cxLaAgrXAlt7ImtleSI6ICI5
|
||||
OGYzYjFkNDdjZTk2OWNmMDU3NzI3Yjc4NDE0MjVjZCIsICJpZCI6ICI5OTJkZjYyZi1kY2FiLTQy
|
||||
OTUtOTIwNi05MDBkNDExNGIxZTkiLCAicm9sZSI6ICJGcmllbmRseSBOZWlnaGJvciIsICJ2ZXJi
|
||||
b3NlPyI6IGZhbHNlLCAibWF4X2l0ZXIiOiAyMCwgIm1heF9ycG0iOiBudWxsLCAiZnVuY3Rpb25f
|
||||
Y2FsbGluZ19sbG0iOiAiIiwgImxsbSI6ICJncHQtNG8tbWluaSIsICJkZWxlZ2F0aW9uX2VuYWJs
|
||||
ZWQ/IjogZmFsc2UsICJhbGxvd19jb2RlX2V4ZWN1dGlvbj8iOiBmYWxzZSwgIm1heF9yZXRyeV9s
|
||||
aW1pdCI6IDIsICJ0b29sc19uYW1lcyI6IFsiZGVjaWRlIGdyZWV0aW5ncyJdfV1KmAIKCmNyZXdf
|
||||
dGFza3MSiQIKhgJbeyJrZXkiOiAiODBkN2JjZDQ5MDk5MjkwMDgzODMyZjBlOTgzMzgwZGYiLCAi
|
||||
aWQiOiAiMmZmNjE5N2UtYmEyNy00YjczLWI0YTctNGZhMDQ4ZTYyYjQ3IiwgImFzeW5jX2V4ZWN1
|
||||
dGlvbj8iOiBmYWxzZSwgImh1bWFuX2lucHV0PyI6IGZhbHNlLCAiYWdlbnRfcm9sZSI6ICJGcmll
|
||||
bmRseSBOZWlnaGJvciIsICJhZ2VudF9rZXkiOiAiOThmM2IxZDQ3Y2U5NjljZjA1NzcyN2I3ODQx
|
||||
NDI1Y2QiLCAidG9vbHNfbmFtZXMiOiBbImRlY2lkZSBncmVldGluZ3MiXX1degIYAYUBAAEAABKO
|
||||
AgoQnjTp5boK7/+DQxztYIpqihIIgGnMUkBtzHEqDFRhc2sgQ3JlYXRlZDABOcpYcuRvKBUYQalE
|
||||
c+RvKBUYSi4KCGNyZXdfa2V5EiIKIGMzMDc2MDA5MzI2NzYxNDQ0ZDU3YzcxZDFkYTNmMjdjSjEK
|
||||
B2NyZXdfaWQSJgokNzk0MDE5MjUtYjhlOS00NzA4LTg1MzAtNDQ4YWZhM2JmOGIwSi4KCHRhc2tf
|
||||
a2V5EiIKIDgwZDdiY2Q0OTA5OTI5MDA4MzgzMmYwZTk4MzM4MGRmSjEKB3Rhc2tfaWQSJgokMmZm
|
||||
NjE5N2UtYmEyNy00YjczLWI0YTctNGZhMDQ4ZTYyYjQ3egIYAYUBAAEAABKTAQoQ26H9pLUgswDN
|
||||
p9XhJwwL6BIIx3bw7mAvPYwqClRvb2wgVXNhZ2UwATmy7NPlbygVGEEvb+HlbygVGEoaCg5jcmV3
|
||||
YWlfdmVyc2lvbhIICgYwLjg2LjBKHwoJdG9vbF9uYW1lEhIKEERlY2lkZSBHcmVldGluZ3NKDgoI
|
||||
YXR0ZW1wdHMSAhgBegIYAYUBAAEAAA==
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Length:
|
||||
- '2986'
|
||||
Content-Type:
|
||||
- application/x-protobuf
|
||||
User-Agent:
|
||||
- OTel-OTLP-Exporter-Python/1.27.0
|
||||
method: POST
|
||||
uri: https://telemetry.crewai.com:4319/v1/traces
|
||||
response:
|
||||
body:
|
||||
string: "\n\0"
|
||||
headers:
|
||||
Content-Length:
|
||||
- '2'
|
||||
Content-Type:
|
||||
- application/x-protobuf
|
||||
Date:
|
||||
- Fri, 27 Dec 2024 22:14:53 GMT
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
- request:
|
||||
body: '{"messages": [{"role": "system", "content": "You are test role. test backstory\nYour
|
||||
personal goal is: test goal\nTo give my best complete final answer to the task
|
||||
@@ -105,20 +22,18 @@ interactions:
|
||||
- '824'
|
||||
content-type:
|
||||
- application/json
|
||||
cookie:
|
||||
- _cfuvid=ePJSDFdHag2D8lj21_ijAMWjoA6xfnPNxN4uekvC728-1727226247743-0.0.1.1-604800000
|
||||
host:
|
||||
- api.openai.com
|
||||
user-agent:
|
||||
- OpenAI/Python 1.52.1
|
||||
x-stainless-arch:
|
||||
- x64
|
||||
- arm64
|
||||
x-stainless-async:
|
||||
- 'false'
|
||||
x-stainless-lang:
|
||||
- python
|
||||
x-stainless-os:
|
||||
- Linux
|
||||
- MacOS
|
||||
x-stainless-package-version:
|
||||
- 1.52.1
|
||||
x-stainless-raw-response:
|
||||
@@ -132,8 +47,8 @@ interactions:
|
||||
method: POST
|
||||
uri: https://api.openai.com/v1/chat/completions
|
||||
response:
|
||||
content: "{\n \"id\": \"chatcmpl-AjCtZLLrWi8ZASpP9bz6HaCV7xBIn\",\n \"object\":
|
||||
\"chat.completion\",\n \"created\": 1735337693,\n \"model\": \"gpt-4o-mini-2024-07-18\",\n
|
||||
content: "{\n \"id\": \"chatcmpl-AaqIIsTxhvf75xvuu7gQScIlRSKbW\",\n \"object\":
|
||||
\"chat.completion\",\n \"created\": 1733344190,\n \"model\": \"gpt-4o-mini-2024-07-18\",\n
|
||||
\ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\":
|
||||
\"assistant\",\n \"content\": \"I now can give a great answer \\nFinal
|
||||
Answer: Hi\",\n \"refusal\": null\n },\n \"logprobs\": null,\n
|
||||
@@ -142,12 +57,12 @@ interactions:
|
||||
{\n \"cached_tokens\": 0,\n \"audio_tokens\": 0\n },\n \"completion_tokens_details\":
|
||||
{\n \"reasoning_tokens\": 0,\n \"audio_tokens\": 0,\n \"accepted_prediction_tokens\":
|
||||
0,\n \"rejected_prediction_tokens\": 0\n }\n },\n \"system_fingerprint\":
|
||||
\"fp_0aa8d3e20b\"\n}\n"
|
||||
\"fp_0705bf87c0\"\n}\n"
|
||||
headers:
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-RAY:
|
||||
- 8f8caa83deca756b-SEA
|
||||
- 8ece8cfc3b1f4532-ATL
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Encoding:
|
||||
@@ -155,14 +70,14 @@ interactions:
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Fri, 27 Dec 2024 22:14:53 GMT
|
||||
- Wed, 04 Dec 2024 20:29:50 GMT
|
||||
Server:
|
||||
- cloudflare
|
||||
Set-Cookie:
|
||||
- __cf_bm=wJkq_yLkzE3OdxE0aMJz.G0kce969.9JxRmZ0ratl4c-1735337693-1.0.1.1-OKpUoRrSPFGvWv5Hp5ET1PNZ7iZNHPKEAuakpcQUxxPSeisUIIR3qIOZ31MGmYugqB5.wkvidgbxOAagqJvmnw;
|
||||
path=/; expires=Fri, 27-Dec-24 22:44:53 GMT; domain=.api.openai.com; HttpOnly;
|
||||
- __cf_bm=QJZZjZ6eqnVamqUkw.Bx0mj7oBi3a_vGEH1VODcUxlg-1733344190-1.0.1.1-xyN0ekA9xIrSwEhRBmTiWJ3Pt72UYLU5owKfkz5yihVmMTfsr_Qz.ssGPJ5cuft066v1xVjb4zOSTdFmesMSKg;
|
||||
path=/; expires=Wed, 04-Dec-24 20:59:50 GMT; domain=.api.openai.com; HttpOnly;
|
||||
Secure; SameSite=None
|
||||
- _cfuvid=A_ASCLNAVfQoyucWOAIhecWtEpNotYoZr0bAFihgNxs-1735337693273-0.0.1.1-604800000;
|
||||
- _cfuvid=eCIkP8GVPvpkg19eOhCquWFHm.RTQBQy4yHLGGEAH5c-1733344190334-0.0.1.1-604800000;
|
||||
path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
@@ -175,7 +90,7 @@ interactions:
|
||||
openai-organization:
|
||||
- crewai-iuxna1
|
||||
openai-processing-ms:
|
||||
- '404'
|
||||
- '313'
|
||||
openai-version:
|
||||
- '2020-10-01'
|
||||
strict-transport-security:
|
||||
@@ -193,7 +108,7 @@ interactions:
|
||||
x-ratelimit-reset-tokens:
|
||||
- 0s
|
||||
x-request-id:
|
||||
- req_6ac84634bff9193743c4b0911c09b4a6
|
||||
- req_9fd9a8ee688045dcf7ac5f6fdf689372
|
||||
http_version: HTTP/1.1
|
||||
status_code: 200
|
||||
- request:
|
||||
@@ -216,20 +131,20 @@ interactions:
|
||||
content-type:
|
||||
- application/json
|
||||
cookie:
|
||||
- _cfuvid=A_ASCLNAVfQoyucWOAIhecWtEpNotYoZr0bAFihgNxs-1735337693273-0.0.1.1-604800000;
|
||||
__cf_bm=wJkq_yLkzE3OdxE0aMJz.G0kce969.9JxRmZ0ratl4c-1735337693-1.0.1.1-OKpUoRrSPFGvWv5Hp5ET1PNZ7iZNHPKEAuakpcQUxxPSeisUIIR3qIOZ31MGmYugqB5.wkvidgbxOAagqJvmnw
|
||||
- __cf_bm=QJZZjZ6eqnVamqUkw.Bx0mj7oBi3a_vGEH1VODcUxlg-1733344190-1.0.1.1-xyN0ekA9xIrSwEhRBmTiWJ3Pt72UYLU5owKfkz5yihVmMTfsr_Qz.ssGPJ5cuft066v1xVjb4zOSTdFmesMSKg;
|
||||
_cfuvid=eCIkP8GVPvpkg19eOhCquWFHm.RTQBQy4yHLGGEAH5c-1733344190334-0.0.1.1-604800000
|
||||
host:
|
||||
- api.openai.com
|
||||
user-agent:
|
||||
- OpenAI/Python 1.52.1
|
||||
x-stainless-arch:
|
||||
- x64
|
||||
- arm64
|
||||
x-stainless-async:
|
||||
- 'false'
|
||||
x-stainless-lang:
|
||||
- python
|
||||
x-stainless-os:
|
||||
- Linux
|
||||
- MacOS
|
||||
x-stainless-package-version:
|
||||
- 1.52.1
|
||||
x-stainless-raw-response:
|
||||
@@ -243,8 +158,8 @@ interactions:
|
||||
method: POST
|
||||
uri: https://api.openai.com/v1/chat/completions
|
||||
response:
|
||||
content: "{\n \"id\": \"chatcmpl-AjCtZNlWdrrPZhq0MJDqd16sMuQEJ\",\n \"object\":
|
||||
\"chat.completion\",\n \"created\": 1735337693,\n \"model\": \"gpt-4o-mini-2024-07-18\",\n
|
||||
content: "{\n \"id\": \"chatcmpl-AaqIIaQlLyoyPmk909PvAIfA2TmJL\",\n \"object\":
|
||||
\"chat.completion\",\n \"created\": 1733344190,\n \"model\": \"gpt-4o-mini-2024-07-18\",\n
|
||||
\ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\":
|
||||
\"assistant\",\n \"content\": \"True\",\n \"refusal\": null\n
|
||||
\ },\n \"logprobs\": null,\n \"finish_reason\": \"stop\"\n }\n
|
||||
@@ -253,12 +168,12 @@ interactions:
|
||||
0,\n \"audio_tokens\": 0\n },\n \"completion_tokens_details\": {\n
|
||||
\ \"reasoning_tokens\": 0,\n \"audio_tokens\": 0,\n \"accepted_prediction_tokens\":
|
||||
0,\n \"rejected_prediction_tokens\": 0\n }\n },\n \"system_fingerprint\":
|
||||
\"fp_0aa8d3e20b\"\n}\n"
|
||||
\"fp_0705bf87c0\"\n}\n"
|
||||
headers:
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-RAY:
|
||||
- 8f8caa87094f756b-SEA
|
||||
- 8ece8d060b5e4532-ATL
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Encoding:
|
||||
@@ -266,7 +181,7 @@ interactions:
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Fri, 27 Dec 2024 22:14:53 GMT
|
||||
- Wed, 04 Dec 2024 20:29:50 GMT
|
||||
Server:
|
||||
- cloudflare
|
||||
Transfer-Encoding:
|
||||
@@ -280,7 +195,7 @@ interactions:
|
||||
openai-organization:
|
||||
- crewai-iuxna1
|
||||
openai-processing-ms:
|
||||
- '156'
|
||||
- '375'
|
||||
openai-version:
|
||||
- '2020-10-01'
|
||||
strict-transport-security:
|
||||
@@ -298,7 +213,7 @@ interactions:
|
||||
x-ratelimit-reset-tokens:
|
||||
- 0s
|
||||
x-request-id:
|
||||
- req_ec74bef2a9ef7b2144c03fd7f7bbeab0
|
||||
- req_be7cb475e0859a82c37ee3f2871ea5ea
|
||||
http_version: HTTP/1.1
|
||||
status_code: 200
|
||||
- request:
|
||||
@@ -327,20 +242,20 @@ interactions:
|
||||
content-type:
|
||||
- application/json
|
||||
cookie:
|
||||
- _cfuvid=A_ASCLNAVfQoyucWOAIhecWtEpNotYoZr0bAFihgNxs-1735337693273-0.0.1.1-604800000;
|
||||
__cf_bm=wJkq_yLkzE3OdxE0aMJz.G0kce969.9JxRmZ0ratl4c-1735337693-1.0.1.1-OKpUoRrSPFGvWv5Hp5ET1PNZ7iZNHPKEAuakpcQUxxPSeisUIIR3qIOZ31MGmYugqB5.wkvidgbxOAagqJvmnw
|
||||
- __cf_bm=QJZZjZ6eqnVamqUkw.Bx0mj7oBi3a_vGEH1VODcUxlg-1733344190-1.0.1.1-xyN0ekA9xIrSwEhRBmTiWJ3Pt72UYLU5owKfkz5yihVmMTfsr_Qz.ssGPJ5cuft066v1xVjb4zOSTdFmesMSKg;
|
||||
_cfuvid=eCIkP8GVPvpkg19eOhCquWFHm.RTQBQy4yHLGGEAH5c-1733344190334-0.0.1.1-604800000
|
||||
host:
|
||||
- api.openai.com
|
||||
user-agent:
|
||||
- OpenAI/Python 1.52.1
|
||||
x-stainless-arch:
|
||||
- x64
|
||||
- arm64
|
||||
x-stainless-async:
|
||||
- 'false'
|
||||
x-stainless-lang:
|
||||
- python
|
||||
x-stainless-os:
|
||||
- Linux
|
||||
- MacOS
|
||||
x-stainless-package-version:
|
||||
- 1.52.1
|
||||
x-stainless-raw-response:
|
||||
@@ -354,23 +269,22 @@ interactions:
|
||||
method: POST
|
||||
uri: https://api.openai.com/v1/chat/completions
|
||||
response:
|
||||
content: "{\n \"id\": \"chatcmpl-AjCtZGv4f3h7GDdhyOy9G0sB1lRgC\",\n \"object\":
|
||||
\"chat.completion\",\n \"created\": 1735337693,\n \"model\": \"gpt-4o-mini-2024-07-18\",\n
|
||||
content: "{\n \"id\": \"chatcmpl-AaqIJAAxpVfUOdrsgYKHwfRlHv4RS\",\n \"object\":
|
||||
\"chat.completion\",\n \"created\": 1733344191,\n \"model\": \"gpt-4o-mini-2024-07-18\",\n
|
||||
\ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\":
|
||||
\"assistant\",\n \"content\": \"Thought: I understand the feedback and
|
||||
will adjust my response accordingly. \\nFinal Answer: Hello\",\n \"refusal\":
|
||||
null\n },\n \"logprobs\": null,\n \"finish_reason\": \"stop\"\n
|
||||
\ }\n ],\n \"usage\": {\n \"prompt_tokens\": 188,\n \"completion_tokens\":
|
||||
18,\n \"total_tokens\": 206,\n \"prompt_tokens_details\": {\n \"cached_tokens\":
|
||||
0,\n \"audio_tokens\": 0\n },\n \"completion_tokens_details\": {\n
|
||||
\ \"reasoning_tokens\": 0,\n \"audio_tokens\": 0,\n \"accepted_prediction_tokens\":
|
||||
\"assistant\",\n \"content\": \"Thought: I now can give a great answer
|
||||
\ \\nFinal Answer: Hello\",\n \"refusal\": null\n },\n \"logprobs\":
|
||||
null,\n \"finish_reason\": \"stop\"\n }\n ],\n \"usage\": {\n \"prompt_tokens\":
|
||||
188,\n \"completion_tokens\": 14,\n \"total_tokens\": 202,\n \"prompt_tokens_details\":
|
||||
{\n \"cached_tokens\": 0,\n \"audio_tokens\": 0\n },\n \"completion_tokens_details\":
|
||||
{\n \"reasoning_tokens\": 0,\n \"audio_tokens\": 0,\n \"accepted_prediction_tokens\":
|
||||
0,\n \"rejected_prediction_tokens\": 0\n }\n },\n \"system_fingerprint\":
|
||||
\"fp_0aa8d3e20b\"\n}\n"
|
||||
\"fp_0705bf87c0\"\n}\n"
|
||||
headers:
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-RAY:
|
||||
- 8f8caa88cac4756b-SEA
|
||||
- 8ece8d090fc34532-ATL
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Encoding:
|
||||
@@ -378,7 +292,7 @@ interactions:
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Fri, 27 Dec 2024 22:14:54 GMT
|
||||
- Wed, 04 Dec 2024 20:29:51 GMT
|
||||
Server:
|
||||
- cloudflare
|
||||
Transfer-Encoding:
|
||||
@@ -392,7 +306,7 @@ interactions:
|
||||
openai-organization:
|
||||
- crewai-iuxna1
|
||||
openai-processing-ms:
|
||||
- '358'
|
||||
- '484'
|
||||
openai-version:
|
||||
- '2020-10-01'
|
||||
strict-transport-security:
|
||||
@@ -410,7 +324,7 @@ interactions:
|
||||
x-ratelimit-reset-tokens:
|
||||
- 0s
|
||||
x-request-id:
|
||||
- req_ae1ab6b206d28ded6fee3c83ed0c2ab7
|
||||
- req_5bf4a565ad6c2567a1ed204ecac89134
|
||||
http_version: HTTP/1.1
|
||||
status_code: 200
|
||||
- request:
|
||||
@@ -432,20 +346,20 @@ interactions:
|
||||
content-type:
|
||||
- application/json
|
||||
cookie:
|
||||
- _cfuvid=A_ASCLNAVfQoyucWOAIhecWtEpNotYoZr0bAFihgNxs-1735337693273-0.0.1.1-604800000;
|
||||
__cf_bm=wJkq_yLkzE3OdxE0aMJz.G0kce969.9JxRmZ0ratl4c-1735337693-1.0.1.1-OKpUoRrSPFGvWv5Hp5ET1PNZ7iZNHPKEAuakpcQUxxPSeisUIIR3qIOZ31MGmYugqB5.wkvidgbxOAagqJvmnw
|
||||
- __cf_bm=QJZZjZ6eqnVamqUkw.Bx0mj7oBi3a_vGEH1VODcUxlg-1733344190-1.0.1.1-xyN0ekA9xIrSwEhRBmTiWJ3Pt72UYLU5owKfkz5yihVmMTfsr_Qz.ssGPJ5cuft066v1xVjb4zOSTdFmesMSKg;
|
||||
_cfuvid=eCIkP8GVPvpkg19eOhCquWFHm.RTQBQy4yHLGGEAH5c-1733344190334-0.0.1.1-604800000
|
||||
host:
|
||||
- api.openai.com
|
||||
user-agent:
|
||||
- OpenAI/Python 1.52.1
|
||||
x-stainless-arch:
|
||||
- x64
|
||||
- arm64
|
||||
x-stainless-async:
|
||||
- 'false'
|
||||
x-stainless-lang:
|
||||
- python
|
||||
x-stainless-os:
|
||||
- Linux
|
||||
- MacOS
|
||||
x-stainless-package-version:
|
||||
- 1.52.1
|
||||
x-stainless-raw-response:
|
||||
@@ -459,8 +373,8 @@ interactions:
|
||||
method: POST
|
||||
uri: https://api.openai.com/v1/chat/completions
|
||||
response:
|
||||
content: "{\n \"id\": \"chatcmpl-AjCtaiHL4TY8Dssk0j2miqmjrzquy\",\n \"object\":
|
||||
\"chat.completion\",\n \"created\": 1735337694,\n \"model\": \"gpt-4o-mini-2024-07-18\",\n
|
||||
content: "{\n \"id\": \"chatcmpl-AaqIJqyG8vl9mxj2qDPZgaxyNLLIq\",\n \"object\":
|
||||
\"chat.completion\",\n \"created\": 1733344191,\n \"model\": \"gpt-4o-mini-2024-07-18\",\n
|
||||
\ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\":
|
||||
\"assistant\",\n \"content\": \"False\",\n \"refusal\": null\n
|
||||
\ },\n \"logprobs\": null,\n \"finish_reason\": \"stop\"\n }\n
|
||||
@@ -469,12 +383,12 @@ interactions:
|
||||
0,\n \"audio_tokens\": 0\n },\n \"completion_tokens_details\": {\n
|
||||
\ \"reasoning_tokens\": 0,\n \"audio_tokens\": 0,\n \"accepted_prediction_tokens\":
|
||||
0,\n \"rejected_prediction_tokens\": 0\n }\n },\n \"system_fingerprint\":
|
||||
\"fp_0aa8d3e20b\"\n}\n"
|
||||
\"fp_0705bf87c0\"\n}\n"
|
||||
headers:
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-RAY:
|
||||
- 8f8caa8bdd26756b-SEA
|
||||
- 8ece8d0cfdeb4532-ATL
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Encoding:
|
||||
@@ -482,7 +396,7 @@ interactions:
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Fri, 27 Dec 2024 22:14:54 GMT
|
||||
- Wed, 04 Dec 2024 20:29:51 GMT
|
||||
Server:
|
||||
- cloudflare
|
||||
Transfer-Encoding:
|
||||
@@ -496,7 +410,7 @@ interactions:
|
||||
openai-organization:
|
||||
- crewai-iuxna1
|
||||
openai-processing-ms:
|
||||
- '184'
|
||||
- '341'
|
||||
openai-version:
|
||||
- '2020-10-01'
|
||||
strict-transport-security:
|
||||
@@ -514,7 +428,7 @@ interactions:
|
||||
x-ratelimit-reset-tokens:
|
||||
- 0s
|
||||
x-request-id:
|
||||
- req_652891f79c1104a7a8436275d78a69f1
|
||||
- req_5554bade8ceda00cf364b76a51b708ff
|
||||
http_version: HTTP/1.1
|
||||
status_code: 200
|
||||
version: 1
|
||||
|
||||
@@ -1123,7 +1123,7 @@ def test_kickoff_for_each_empty_input():
|
||||
assert results == []
|
||||
|
||||
|
||||
@pytest.mark.vcr(filter_headeruvs=["authorization"])
|
||||
@pytest.mark.vcr(filter_headers=["authorization"])
|
||||
def test_kickoff_for_each_invalid_input():
|
||||
"""Tests if kickoff_for_each raises TypeError for invalid input types."""
|
||||
|
||||
@@ -3125,4 +3125,4 @@ def test_multimodal_agent_live_image_analysis():
|
||||
# Verify we got a meaningful response
|
||||
assert isinstance(result.raw, str)
|
||||
assert len(result.raw) > 100 # Expecting a detailed analysis
|
||||
assert "error" not in result.raw.lower() # No error messages in response
|
||||
assert "error" not in result.raw.lower() # No error messages in response
|
||||
@@ -124,120 +124,3 @@ def test_ask_question_to_wrong_agent():
|
||||
result
|
||||
== "\nError executing tool. coworker mentioned not found, it must be one of the following options:\n- researcher\n"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.vcr(filter_headers=["authorization"])
|
||||
def test_delegate_work_with_null_allowed_agents():
|
||||
"""Test delegation when allowed_agents is None (unrestricted delegation)."""
|
||||
executive = Agent(
|
||||
role="Executive Director",
|
||||
goal="Lead the team effectively",
|
||||
backstory="You're an experienced executive",
|
||||
allow_delegation=True,
|
||||
allowed_agents=None
|
||||
)
|
||||
|
||||
research_manager = Agent(
|
||||
role="Research Manager",
|
||||
goal="Manage research",
|
||||
backstory="You're a research expert",
|
||||
allow_delegation=False
|
||||
)
|
||||
|
||||
tools = AgentTools(agents=[executive, research_manager]).tools()
|
||||
delegate_tool = tools[0]
|
||||
|
||||
result = delegate_tool.run(
|
||||
coworker="Research Manager",
|
||||
task="Handle research",
|
||||
context="Important research"
|
||||
)
|
||||
assert "Error" not in result
|
||||
|
||||
|
||||
@pytest.mark.vcr(filter_headers=["authorization"])
|
||||
def test_delegate_work_with_empty_allowed_agents():
|
||||
"""Test delegation when allowed_agents is an empty list (no delegation allowed)."""
|
||||
executive = Agent(
|
||||
role="Executive Director",
|
||||
goal="Lead the team effectively",
|
||||
backstory="You're an experienced executive",
|
||||
allow_delegation=True,
|
||||
allowed_agents=[]
|
||||
)
|
||||
|
||||
research_manager = Agent(
|
||||
role="Research Manager",
|
||||
goal="Manage research",
|
||||
backstory="You're a research expert",
|
||||
allow_delegation=False
|
||||
)
|
||||
|
||||
tools = AgentTools(agents=[executive, research_manager]).tools()
|
||||
delegate_tool = tools[0]
|
||||
|
||||
result = delegate_tool.run(
|
||||
coworker="Research Manager",
|
||||
task="Handle research",
|
||||
context="Important research"
|
||||
)
|
||||
assert "Error" in result
|
||||
assert "Authorization Error" in result
|
||||
|
||||
|
||||
@pytest.mark.vcr(filter_headers=["authorization"])
|
||||
def test_delegate_work_with_allowed_agents():
|
||||
executive = Agent(
|
||||
role="Executive Director",
|
||||
goal="Lead the team effectively",
|
||||
backstory="You're an experienced executive",
|
||||
allow_delegation=True,
|
||||
allowed_agents=["Communications Manager"]
|
||||
)
|
||||
|
||||
comms_manager = Agent(
|
||||
role="Communications Manager",
|
||||
goal="Manage communications",
|
||||
backstory="You're a communications expert",
|
||||
allow_delegation=False
|
||||
)
|
||||
|
||||
tools = AgentTools(agents=[executive, comms_manager]).tools()
|
||||
delegate_tool = tools[0]
|
||||
|
||||
result = delegate_tool.run(
|
||||
coworker="Communications Manager",
|
||||
task="Handle PR",
|
||||
context="Important announcement"
|
||||
)
|
||||
assert "Error" not in result
|
||||
|
||||
|
||||
@pytest.mark.vcr(filter_headers=["authorization"])
|
||||
def test_delegate_work_with_unauthorized_agent():
|
||||
executive = Agent(
|
||||
role="Executive Director",
|
||||
goal="Lead the team effectively",
|
||||
backstory="You're an experienced executive",
|
||||
allow_delegation=True,
|
||||
allowed_agents=["Communications Manager"]
|
||||
)
|
||||
|
||||
research_manager = Agent(
|
||||
role="Research Manager",
|
||||
goal="Manage research",
|
||||
backstory="You're a research expert",
|
||||
allow_delegation=False
|
||||
)
|
||||
|
||||
tools = AgentTools(agents=[executive, research_manager]).tools()
|
||||
delegate_tool = tools[0]
|
||||
|
||||
result = delegate_tool.run(
|
||||
coworker="Research Manager",
|
||||
task="Handle research",
|
||||
context="Important research"
|
||||
)
|
||||
assert "Error" in result
|
||||
assert "Authorization Error" in result
|
||||
assert "cannot delegate to" in result
|
||||
|
||||
@@ -1,711 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: !!binary |
|
||||
Cu3qAQokCiIKDHNlcnZpY2UubmFtZRISChBjcmV3QUktdGVsZW1ldHJ5EsPqAQoSChBjcmV3YWku
|
||||
dGVsZW1ldHJ5EpoMChARlLabatMnFZSLpOwfZlkDEghSZQoo9w8uZioMQ3JldyBDcmVhdGVkMAE5
|
||||
XsrSa7KiIhhBReHia7KiIhhKGgoOY3Jld2FpX3ZlcnNpb24SCAoGMC44Ni4wShoKDnB5dGhvbl92
|
||||
ZXJzaW9uEggKBjMuMTIuN0ouCghjcmV3X2tleRIiCiAxZjEyOGJkYjdiYWE0YjY3NzE0ZjFkYWVk
|
||||
YzJmM2FiNkoxCgdjcmV3X2lkEiYKJDZiNTYwZDMwLWIwNzMtNDdmYy05OWNkLWQ4OTUwYTAwYzcx
|
||||
ZUocCgxjcmV3X3Byb2Nlc3MSDAoKc2VxdWVudGlhbEoRCgtjcmV3X21lbW9yeRICEABKGgoUY3Jl
|
||||
d19udW1iZXJfb2ZfdGFza3MSAhgCShsKFWNyZXdfbnVtYmVyX29mX2FnZW50cxICGAJKtAUKC2Ny
|
||||
ZXdfYWdlbnRzEqQFCqEFW3sia2V5IjogIjczYzM0OWM5M2MxNjNiNWQ0ZGY5OGE2NGZhYzFjNDMw
|
||||
IiwgImlkIjogIjdhZThhYTEyLTEzMDQtNGMyYi1hYWU4LTE2N2Q5YTMyNmFjNyIsICJyb2xlIjog
|
||||
Int0b3BpY30gU2VuaW9yIERhdGEgUmVzZWFyY2hlclxuIiwgInZlcmJvc2U/IjogdHJ1ZSwgIm1h
|
||||
eF9pdGVyIjogMjAsICJtYXhfcnBtIjogbnVsbCwgImZ1bmN0aW9uX2NhbGxpbmdfbGxtIjogIiIs
|
||||
ICJsbG0iOiAiZ3B0LTRvLW1pbmkiLCAiZGVsZWdhdGlvbl9lbmFibGVkPyI6IGZhbHNlLCAiYWxs
|
||||
b3dfY29kZV9leGVjdXRpb24/IjogZmFsc2UsICJtYXhfcmV0cnlfbGltaXQiOiAyLCAidG9vbHNf
|
||||
bmFtZXMiOiBbXX0sIHsia2V5IjogIjEwNGZlMDY1OWUxMGI0MjZjZjg4ZjAyNGZiNTcxNTUzIiwg
|
||||
ImlkIjogIjNhMDdiMmQxLWM3OTgtNDViNS1hMjkzLTQyYTc4YTU5Y2Y4NyIsICJyb2xlIjogInt0
|
||||
b3BpY30gUmVwb3J0aW5nIEFuYWx5c3RcbiIsICJ2ZXJib3NlPyI6IHRydWUsICJtYXhfaXRlciI6
|
||||
IDIwLCAibWF4X3JwbSI6IG51bGwsICJmdW5jdGlvbl9jYWxsaW5nX2xsbSI6ICIiLCAibGxtIjog
|
||||
ImdwdC00by1taW5pIiwgImRlbGVnYXRpb25fZW5hYmxlZD8iOiBmYWxzZSwgImFsbG93X2NvZGVf
|
||||
ZXhlY3V0aW9uPyI6IGZhbHNlLCAibWF4X3JldHJ5X2xpbWl0IjogMiwgInRvb2xzX25hbWVzIjog
|
||||
W119XUqTBAoKY3Jld190YXNrcxKEBAqBBFt7ImtleSI6ICI2YWZjNGIzOTYyNTlmYmI3NjgxZjU2
|
||||
Yzc3NTVjYzkzNyIsICJpZCI6ICJkMzM1ZDFjYi02ZmM2LTQ1ZjYtOTRmNy0zNjMxZGExZWQzMzYi
|
||||
LCAiYXN5bmNfZXhlY3V0aW9uPyI6IGZhbHNlLCAiaHVtYW5faW5wdXQ/IjogZmFsc2UsICJhZ2Vu
|
||||
dF9yb2xlIjogInt0b3BpY30gU2VuaW9yIERhdGEgUmVzZWFyY2hlclxuIiwgImFnZW50X2tleSI6
|
||||
ICI3M2MzNDljOTNjMTYzYjVkNGRmOThhNjRmYWMxYzQzMCIsICJ0b29sc19uYW1lcyI6IFtdfSwg
|
||||
eyJrZXkiOiAiYjE3YjE4OGRiZjE0ZjkzYTk4ZTViOTVhYWQzNjc1NzciLCAiaWQiOiAiMjM2Y2M5
|
||||
NzgtNzA3NC00ZTczLWFlYjAtNzcwMWMzNjM3MDMyIiwgImFzeW5jX2V4ZWN1dGlvbj8iOiBmYWxz
|
||||
ZSwgImh1bWFuX2lucHV0PyI6IGZhbHNlLCAiYWdlbnRfcm9sZSI6ICJ7dG9waWN9IFJlcG9ydGlu
|
||||
ZyBBbmFseXN0XG4iLCAiYWdlbnRfa2V5IjogIjEwNGZlMDY1OWUxMGI0MjZjZjg4ZjAyNGZiNTcx
|
||||
NTUzIiwgInRvb2xzX25hbWVzIjogW119XXoCGAGFAQABAAASjgIKEI6MwNv16Ttc4QY8qJr9bwES
|
||||
CDMy2kCWPy5ZKgxUYXNrIENyZWF0ZWQwATkH4g1ssqIiGEFj1g5ssqIiGEouCghjcmV3X2tleRIi
|
||||
CiAxZjEyOGJkYjdiYWE0YjY3NzE0ZjFkYWVkYzJmM2FiNkoxCgdjcmV3X2lkEiYKJDZiNTYwZDMw
|
||||
LWIwNzMtNDdmYy05OWNkLWQ4OTUwYTAwYzcxZUouCgh0YXNrX2tleRIiCiA2YWZjNGIzOTYyNTlm
|
||||
YmI3NjgxZjU2Yzc3NTVjYzkzN0oxCgd0YXNrX2lkEiYKJGQzMzVkMWNiLTZmYzYtNDVmNi05NGY3
|
||||
LTM2MzFkYTFlZDMzNnoCGAGFAQABAAASjgIKEID9t/vWNPiR/iizWg+FlAYSCNtAa5PMLtw6KgxU
|
||||
YXNrIENyZWF0ZWQwATnQIsJvsqIiGEETNcNvsqIiGEouCghjcmV3X2tleRIiCiAxZjEyOGJkYjdi
|
||||
YWE0YjY3NzE0ZjFkYWVkYzJmM2FiNkoxCgdjcmV3X2lkEiYKJDZiNTYwZDMwLWIwNzMtNDdmYy05
|
||||
OWNkLWQ4OTUwYTAwYzcxZUouCgh0YXNrX2tleRIiCiBiMTdiMTg4ZGJmMTRmOTNhOThlNWI5NWFh
|
||||
ZDM2NzU3N0oxCgd0YXNrX2lkEiYKJDIzNmNjOTc4LTcwNzQtNGU3My1hZWIwLTc3MDFjMzYzNzAz
|
||||
MnoCGAGFAQABAAASmgwKEFDKZdD9rEduwRsovihdk6cSCIFqnq8YEbMlKgxDcmV3IENyZWF0ZWQw
|
||||
ATmfh9Z+sqIiGEGZd+V+sqIiGEoaCg5jcmV3YWlfdmVyc2lvbhIICgYwLjg2LjBKGgoOcHl0aG9u
|
||||
X3ZlcnNpb24SCAoGMy4xMi43Si4KCGNyZXdfa2V5EiIKIDFmMTI4YmRiN2JhYTRiNjc3MTRmMWRh
|
||||
ZWRjMmYzYWI2SjEKB2NyZXdfaWQSJgokYWM2NTEyOGEtMzc0My00Y2U0LTk4MWQtNzUwYjk3YjIw
|
||||
NzNkShwKDGNyZXdfcHJvY2VzcxIMCgpzZXF1ZW50aWFsShEKC2NyZXdfbWVtb3J5EgIQAEoaChRj
|
||||
cmV3X251bWJlcl9vZl90YXNrcxICGAJKGwoVY3Jld19udW1iZXJfb2ZfYWdlbnRzEgIYAkq0BQoL
|
||||
Y3Jld19hZ2VudHMSpAUKoQVbeyJrZXkiOiAiNzNjMzQ5YzkzYzE2M2I1ZDRkZjk4YTY0ZmFjMWM0
|
||||
MzAiLCAiaWQiOiAiY2U5NTU5NDctNGFhMy00N2QzLWJhZTgtMDMwYTk5YTZjODY3IiwgInJvbGUi
|
||||
OiAie3RvcGljfSBTZW5pb3IgRGF0YSBSZXNlYXJjaGVyXG4iLCAidmVyYm9zZT8iOiB0cnVlLCAi
|
||||
bWF4X2l0ZXIiOiAyMCwgIm1heF9ycG0iOiBudWxsLCAiZnVuY3Rpb25fY2FsbGluZ19sbG0iOiAi
|
||||
IiwgImxsbSI6ICJncHQtNG8tbWluaSIsICJkZWxlZ2F0aW9uX2VuYWJsZWQ/IjogZmFsc2UsICJh
|
||||
bGxvd19jb2RlX2V4ZWN1dGlvbj8iOiBmYWxzZSwgIm1heF9yZXRyeV9saW1pdCI6IDIsICJ0b29s
|
||||
c19uYW1lcyI6IFtdfSwgeyJrZXkiOiAiMTA0ZmUwNjU5ZTEwYjQyNmNmODhmMDI0ZmI1NzE1NTMi
|
||||
LCAiaWQiOiAiZmMxNmUwMzktOTM0Yi00YmI2LTk4OTItY2I2ODI3MDJkNzUxIiwgInJvbGUiOiAi
|
||||
e3RvcGljfSBSZXBvcnRpbmcgQW5hbHlzdFxuIiwgInZlcmJvc2U/IjogdHJ1ZSwgIm1heF9pdGVy
|
||||
IjogMjAsICJtYXhfcnBtIjogbnVsbCwgImZ1bmN0aW9uX2NhbGxpbmdfbGxtIjogIiIsICJsbG0i
|
||||
OiAiZ3B0LTRvLW1pbmkiLCAiZGVsZWdhdGlvbl9lbmFibGVkPyI6IGZhbHNlLCAiYWxsb3dfY29k
|
||||
ZV9leGVjdXRpb24/IjogZmFsc2UsICJtYXhfcmV0cnlfbGltaXQiOiAyLCAidG9vbHNfbmFtZXMi
|
||||
OiBbXX1dSpMECgpjcmV3X3Rhc2tzEoQECoEEW3sia2V5IjogIjZhZmM0YjM5NjI1OWZiYjc2ODFm
|
||||
NTZjNzc1NWNjOTM3IiwgImlkIjogIjdiMTlhOWM2LWNiZGUtNGZmMC04ZTE5LWQyZTBkZTVkYmQy
|
||||
NSIsICJhc3luY19leGVjdXRpb24/IjogZmFsc2UsICJodW1hbl9pbnB1dD8iOiBmYWxzZSwgImFn
|
||||
ZW50X3JvbGUiOiAie3RvcGljfSBTZW5pb3IgRGF0YSBSZXNlYXJjaGVyXG4iLCAiYWdlbnRfa2V5
|
||||
IjogIjczYzM0OWM5M2MxNjNiNWQ0ZGY5OGE2NGZhYzFjNDMwIiwgInRvb2xzX25hbWVzIjogW119
|
||||
LCB7ImtleSI6ICJiMTdiMTg4ZGJmMTRmOTNhOThlNWI5NWFhZDM2NzU3NyIsICJpZCI6ICJkY2Vi
|
||||
MzNmNi0xZmZhLTRhYmYtYTgxZC1hNGZjZmU4YTBiNmEiLCAiYXN5bmNfZXhlY3V0aW9uPyI6IGZh
|
||||
bHNlLCAiaHVtYW5faW5wdXQ/IjogZmFsc2UsICJhZ2VudF9yb2xlIjogInt0b3BpY30gUmVwb3J0
|
||||
aW5nIEFuYWx5c3RcbiIsICJhZ2VudF9rZXkiOiAiMTA0ZmUwNjU5ZTEwYjQyNmNmODhmMDI0ZmI1
|
||||
NzE1NTMiLCAidG9vbHNfbmFtZXMiOiBbXX1degIYAYUBAAEAABKOAgoQsPkYq1unwFGGPHImp6mP
|
||||
rxIIh9npp70ijY0qDFRhc2sgQ3JlYXRlZDABOb3cEH+yoiIYQYzJEX+yoiIYSi4KCGNyZXdfa2V5
|
||||
EiIKIDFmMTI4YmRiN2JhYTRiNjc3MTRmMWRhZWRjMmYzYWI2SjEKB2NyZXdfaWQSJgokYWM2NTEy
|
||||
OGEtMzc0My00Y2U0LTk4MWQtNzUwYjk3YjIwNzNkSi4KCHRhc2tfa2V5EiIKIDZhZmM0YjM5NjI1
|
||||
OWZiYjc2ODFmNTZjNzc1NWNjOTM3SjEKB3Rhc2tfaWQSJgokN2IxOWE5YzYtY2JkZS00ZmYwLThl
|
||||
MTktZDJlMGRlNWRiZDI1egIYAYUBAAEAABKOAgoQrLgL7kUh3WE0s6Hi8aGswBIID6mZbJgMK3wq
|
||||
DFRhc2sgQ3JlYXRlZDABOdRPjYKyoiIYQT9rjoKyoiIYSi4KCGNyZXdfa2V5EiIKIDFmMTI4YmRi
|
||||
N2JhYTRiNjc3MTRmMWRhZWRjMmYzYWI2SjEKB2NyZXdfaWQSJgokYWM2NTEyOGEtMzc0My00Y2U0
|
||||
LTk4MWQtNzUwYjk3YjIwNzNkSi4KCHRhc2tfa2V5EiIKIGIxN2IxODhkYmYxNGY5M2E5OGU1Yjk1
|
||||
YWFkMzY3NTc3SjEKB3Rhc2tfaWQSJgokZGNlYjMzZjYtMWZmYS00YWJmLWE4MWQtYTRmY2ZlOGEw
|
||||
YjZhegIYAYUBAAEAABKaDAoQYk+rIGf80OzD2lvRykEc5RII1wSitctUDnkqDENyZXcgQ3JlYXRl
|
||||
ZDABOXPlj4+yoiIYQSlHoY+yoiIYShoKDmNyZXdhaV92ZXJzaW9uEggKBjAuODYuMEoaCg5weXRo
|
||||
b25fdmVyc2lvbhIICgYzLjEyLjdKLgoIY3Jld19rZXkSIgogMWYxMjhiZGI3YmFhNGI2NzcxNGYx
|
||||
ZGFlZGMyZjNhYjZKMQoHY3Jld19pZBImCiRmZmJjY2QyZS1jNGMxLTRhNjAtODI2NC00NDJhMTg0
|
||||
ZWJmMWZKHAoMY3Jld19wcm9jZXNzEgwKCnNlcXVlbnRpYWxKEQoLY3Jld19tZW1vcnkSAhAAShoK
|
||||
FGNyZXdfbnVtYmVyX29mX3Rhc2tzEgIYAkobChVjcmV3X251bWJlcl9vZl9hZ2VudHMSAhgCSrQF
|
||||
CgtjcmV3X2FnZW50cxKkBQqhBVt7ImtleSI6ICI3M2MzNDljOTNjMTYzYjVkNGRmOThhNjRmYWMx
|
||||
YzQzMCIsICJpZCI6ICJjZjE2MDJlNC03ZDA0LTQwNTEtYTdmYy04OTc1ODhjMmIzZTAiLCAicm9s
|
||||
ZSI6ICJ7dG9waWN9IFNlbmlvciBEYXRhIFJlc2VhcmNoZXJcbiIsICJ2ZXJib3NlPyI6IHRydWUs
|
||||
ICJtYXhfaXRlciI6IDIwLCAibWF4X3JwbSI6IG51bGwsICJmdW5jdGlvbl9jYWxsaW5nX2xsbSI6
|
||||
ICIiLCAibGxtIjogImdwdC00by1taW5pIiwgImRlbGVnYXRpb25fZW5hYmxlZD8iOiBmYWxzZSwg
|
||||
ImFsbG93X2NvZGVfZXhlY3V0aW9uPyI6IGZhbHNlLCAibWF4X3JldHJ5X2xpbWl0IjogMiwgInRv
|
||||
b2xzX25hbWVzIjogW119LCB7ImtleSI6ICIxMDRmZTA2NTllMTBiNDI2Y2Y4OGYwMjRmYjU3MTU1
|
||||
MyIsICJpZCI6ICJjYmI4ODdmMy0zNjJhLTRiNjctYTM5Yy05MDUyYjcxZDQxZjIiLCAicm9sZSI6
|
||||
ICJ7dG9waWN9IFJlcG9ydGluZyBBbmFseXN0XG4iLCAidmVyYm9zZT8iOiB0cnVlLCAibWF4X2l0
|
||||
ZXIiOiAyMCwgIm1heF9ycG0iOiBudWxsLCAiZnVuY3Rpb25fY2FsbGluZ19sbG0iOiAiIiwgImxs
|
||||
bSI6ICJncHQtNG8tbWluaSIsICJkZWxlZ2F0aW9uX2VuYWJsZWQ/IjogZmFsc2UsICJhbGxvd19j
|
||||
b2RlX2V4ZWN1dGlvbj8iOiBmYWxzZSwgIm1heF9yZXRyeV9saW1pdCI6IDIsICJ0b29sc19uYW1l
|
||||
cyI6IFtdfV1KkwQKCmNyZXdfdGFza3MShAQKgQRbeyJrZXkiOiAiNmFmYzRiMzk2MjU5ZmJiNzY4
|
||||
MWY1NmM3NzU1Y2M5MzciLCAiaWQiOiAiNTY5ZjAxOGQtODMxYS00YjRlLTg5ZDEtNjMxMzI1NDJl
|
||||
MGJmIiwgImFzeW5jX2V4ZWN1dGlvbj8iOiBmYWxzZSwgImh1bWFuX2lucHV0PyI6IGZhbHNlLCAi
|
||||
YWdlbnRfcm9sZSI6ICJ7dG9waWN9IFNlbmlvciBEYXRhIFJlc2VhcmNoZXJcbiIsICJhZ2VudF9r
|
||||
ZXkiOiAiNzNjMzQ5YzkzYzE2M2I1ZDRkZjk4YTY0ZmFjMWM0MzAiLCAidG9vbHNfbmFtZXMiOiBb
|
||||
XX0sIHsia2V5IjogImIxN2IxODhkYmYxNGY5M2E5OGU1Yjk1YWFkMzY3NTc3IiwgImlkIjogImQ0
|
||||
MWIyZDk4LTE4ODMtNDc0OC1iOGY1LTYxZTNjNDg4NDc3NyIsICJhc3luY19leGVjdXRpb24/Ijog
|
||||
ZmFsc2UsICJodW1hbl9pbnB1dD8iOiBmYWxzZSwgImFnZW50X3JvbGUiOiAie3RvcGljfSBSZXBv
|
||||
cnRpbmcgQW5hbHlzdFxuIiwgImFnZW50X2tleSI6ICIxMDRmZTA2NTllMTBiNDI2Y2Y4OGYwMjRm
|
||||
YjU3MTU1MyIsICJ0b29sc19uYW1lcyI6IFtdfV16AhgBhQEAAQAAEo4CChBl4xnClD83luKFHR/v
|
||||
pE37Egja/y+GXMsVtyoMVGFzayBDcmVhdGVkMAE50gvLj7KiIhhBkX/Mj7KiIhhKLgoIY3Jld19r
|
||||
ZXkSIgogMWYxMjhiZGI3YmFhNGI2NzcxNGYxZGFlZGMyZjNhYjZKMQoHY3Jld19pZBImCiRmZmJj
|
||||
Y2QyZS1jNGMxLTRhNjAtODI2NC00NDJhMTg0ZWJmMWZKLgoIdGFza19rZXkSIgogNmFmYzRiMzk2
|
||||
MjU5ZmJiNzY4MWY1NmM3NzU1Y2M5MzdKMQoHdGFza19pZBImCiQ1NjlmMDE4ZC04MzFhLTRiNGUt
|
||||
ODlkMS02MzEzMjU0MmUwYmZ6AhgBhQEAAQAAEo4CChAkMWl37YVNryZc0SU+wTQvEgi92/KhA8QB
|
||||
fCoMVGFzayBDcmVhdGVkMAE5hPmjkrKiIhhB1xOlkrKiIhhKLgoIY3Jld19rZXkSIgogMWYxMjhi
|
||||
ZGI3YmFhNGI2NzcxNGYxZGFlZGMyZjNhYjZKMQoHY3Jld19pZBImCiRmZmJjY2QyZS1jNGMxLTRh
|
||||
NjAtODI2NC00NDJhMTg0ZWJmMWZKLgoIdGFza19rZXkSIgogYjE3YjE4OGRiZjE0ZjkzYTk4ZTVi
|
||||
OTVhYWQzNjc1NzdKMQoHdGFza19pZBImCiRkNDFiMmQ5OC0xODgzLTQ3NDgtYjhmNS02MWUzYzQ4
|
||||
ODQ3Nzd6AhgBhQEAAQAAEpoMChC0T9rA3xl9gd/JzNzoduLBEghip5dA392n3CoMQ3JldyBDcmVh
|
||||
dGVkMAE5H8HMpbKiIhhB4VTcpbKiIhhKGgoOY3Jld2FpX3ZlcnNpb24SCAoGMC44Ni4wShoKDnB5
|
||||
dGhvbl92ZXJzaW9uEggKBjMuMTIuN0ouCghjcmV3X2tleRIiCiAxZjEyOGJkYjdiYWE0YjY3NzE0
|
||||
ZjFkYWVkYzJmM2FiNkoxCgdjcmV3X2lkEiYKJGNkZGZjMGI0LTVmMjgtNGE1Yy04ZDkxLWUxMDE0
|
||||
NWE1MzJkZUocCgxjcmV3X3Byb2Nlc3MSDAoKc2VxdWVudGlhbEoRCgtjcmV3X21lbW9yeRICEABK
|
||||
GgoUY3Jld19udW1iZXJfb2ZfdGFza3MSAhgCShsKFWNyZXdfbnVtYmVyX29mX2FnZW50cxICGAJK
|
||||
tAUKC2NyZXdfYWdlbnRzEqQFCqEFW3sia2V5IjogIjczYzM0OWM5M2MxNjNiNWQ0ZGY5OGE2NGZh
|
||||
YzFjNDMwIiwgImlkIjogIjMwN2I5M2ZhLTM0NTctNDM5My1hNTNiLWY0MTRjMDgxYjVjNCIsICJy
|
||||
b2xlIjogInt0b3BpY30gU2VuaW9yIERhdGEgUmVzZWFyY2hlclxuIiwgInZlcmJvc2U/IjogdHJ1
|
||||
ZSwgIm1heF9pdGVyIjogMjAsICJtYXhfcnBtIjogbnVsbCwgImZ1bmN0aW9uX2NhbGxpbmdfbGxt
|
||||
IjogIiIsICJsbG0iOiAiZ3B0LTRvLW1pbmkiLCAiZGVsZWdhdGlvbl9lbmFibGVkPyI6IGZhbHNl
|
||||
LCAiYWxsb3dfY29kZV9leGVjdXRpb24/IjogZmFsc2UsICJtYXhfcmV0cnlfbGltaXQiOiAyLCAi
|
||||
dG9vbHNfbmFtZXMiOiBbXX0sIHsia2V5IjogIjEwNGZlMDY1OWUxMGI0MjZjZjg4ZjAyNGZiNTcx
|
||||
NTUzIiwgImlkIjogImNiNTUzODA2LTZhY2EtNDVmZC04YjA4LTkzNzIyYTU3MmRjNCIsICJyb2xl
|
||||
IjogInt0b3BpY30gUmVwb3J0aW5nIEFuYWx5c3RcbiIsICJ2ZXJib3NlPyI6IHRydWUsICJtYXhf
|
||||
aXRlciI6IDIwLCAibWF4X3JwbSI6IG51bGwsICJmdW5jdGlvbl9jYWxsaW5nX2xsbSI6ICIiLCAi
|
||||
bGxtIjogImdwdC00by1taW5pIiwgImRlbGVnYXRpb25fZW5hYmxlZD8iOiBmYWxzZSwgImFsbG93
|
||||
X2NvZGVfZXhlY3V0aW9uPyI6IGZhbHNlLCAibWF4X3JldHJ5X2xpbWl0IjogMiwgInRvb2xzX25h
|
||||
bWVzIjogW119XUqTBAoKY3Jld190YXNrcxKEBAqBBFt7ImtleSI6ICI2YWZjNGIzOTYyNTlmYmI3
|
||||
NjgxZjU2Yzc3NTVjYzkzNyIsICJpZCI6ICI0ZGQzZThhMy02NjNjLTQ4NTctODJlOC04ZmZkYjcw
|
||||
YTUwNjMiLCAiYXN5bmNfZXhlY3V0aW9uPyI6IGZhbHNlLCAiaHVtYW5faW5wdXQ/IjogZmFsc2Us
|
||||
ICJhZ2VudF9yb2xlIjogInt0b3BpY30gU2VuaW9yIERhdGEgUmVzZWFyY2hlclxuIiwgImFnZW50
|
||||
X2tleSI6ICI3M2MzNDljOTNjMTYzYjVkNGRmOThhNjRmYWMxYzQzMCIsICJ0b29sc19uYW1lcyI6
|
||||
IFtdfSwgeyJrZXkiOiAiYjE3YjE4OGRiZjE0ZjkzYTk4ZTViOTVhYWQzNjc1NzciLCAiaWQiOiAi
|
||||
ODQyNTg2MzMtNDk0Mi00YWVhLTljNzMtMGVjNDFmM2RjYWMzIiwgImFzeW5jX2V4ZWN1dGlvbj8i
|
||||
OiBmYWxzZSwgImh1bWFuX2lucHV0PyI6IGZhbHNlLCAiYWdlbnRfcm9sZSI6ICJ7dG9waWN9IFJl
|
||||
cG9ydGluZyBBbmFseXN0XG4iLCAiYWdlbnRfa2V5IjogIjEwNGZlMDY1OWUxMGI0MjZjZjg4ZjAy
|
||||
NGZiNTcxNTUzIiwgInRvb2xzX25hbWVzIjogW119XXoCGAGFAQABAAASjgIKEPkO4aYFWuI2zhgC
|
||||
1GCfLyISCFYtEm1Rh1QgKgxUYXNrIENyZWF0ZWQwATkBnQimsqIiGEFQogmmsqIiGEouCghjcmV3
|
||||
X2tleRIiCiAxZjEyOGJkYjdiYWE0YjY3NzE0ZjFkYWVkYzJmM2FiNkoxCgdjcmV3X2lkEiYKJGNk
|
||||
ZGZjMGI0LTVmMjgtNGE1Yy04ZDkxLWUxMDE0NWE1MzJkZUouCgh0YXNrX2tleRIiCiA2YWZjNGIz
|
||||
OTYyNTlmYmI3NjgxZjU2Yzc3NTVjYzkzN0oxCgd0YXNrX2lkEiYKJDRkZDNlOGEzLTY2M2MtNDg1
|
||||
Ny04MmU4LThmZmRiNzBhNTA2M3oCGAGFAQABAAASjgIKEEwNfDNnZvu05eS+khpUMI0SCH5tgNoz
|
||||
pgU9KgxUYXNrIENyZWF0ZWQwATm2rFSpsqIiGEFYyVWpsqIiGEouCghjcmV3X2tleRIiCiAxZjEy
|
||||
OGJkYjdiYWE0YjY3NzE0ZjFkYWVkYzJmM2FiNkoxCgdjcmV3X2lkEiYKJGNkZGZjMGI0LTVmMjgt
|
||||
NGE1Yy04ZDkxLWUxMDE0NWE1MzJkZUouCgh0YXNrX2tleRIiCiBiMTdiMTg4ZGJmMTRmOTNhOThl
|
||||
NWI5NWFhZDM2NzU3N0oxCgd0YXNrX2lkEiYKJDg0MjU4NjMzLTQ5NDItNGFlYS05YzczLTBlYzQx
|
||||
ZjNkY2FjM3oCGAGFAQABAAASmwcKEIjKriyczCTE51idwgWll/oSCNodi2gQB9WWKgxDcmV3IENy
|
||||
ZWF0ZWQwATk8cgG6sqIiGEH6zhK6sqIiGEoaCg5jcmV3YWlfdmVyc2lvbhIICgYwLjg2LjBKGgoO
|
||||
cHl0aG9uX3ZlcnNpb24SCAoGMy4xMi43Si4KCGNyZXdfa2V5EiIKIDVlNmVmZmU2ODBhNWQ5N2Rj
|
||||
Mzg3M2IxNDgyNWNjZmEzSjEKB2NyZXdfaWQSJgokNzhiYmNkY2QtNzViYS00NzhiLWE5MjctMWYx
|
||||
ZGRlMmNjMzljShwKDGNyZXdfcHJvY2VzcxIMCgpzZXF1ZW50aWFsShEKC2NyZXdfbWVtb3J5EgIQ
|
||||
AEoaChRjcmV3X251bWJlcl9vZl90YXNrcxICGAFKGwoVY3Jld19udW1iZXJfb2ZfYWdlbnRzEgIY
|
||||
AUrNAgoLY3Jld19hZ2VudHMSvQIKugJbeyJrZXkiOiAiOTJlN2ViMTkxNjY0YzkzNTc4NWVkN2Q0
|
||||
MjQwYTI5NGQiLCAiaWQiOiAiN2JkNzJhNmQtYTUxMC00NjkyLWIzNGQtMTRhNzA3OTU0MjRiIiwg
|
||||
InJvbGUiOiAiU2NvcmVyIiwgInZlcmJvc2U/IjogZmFsc2UsICJtYXhfaXRlciI6IDIwLCAibWF4
|
||||
X3JwbSI6IG51bGwsICJmdW5jdGlvbl9jYWxsaW5nX2xsbSI6ICIiLCAibGxtIjogImdwdC00by1t
|
||||
aW5pIiwgImRlbGVnYXRpb25fZW5hYmxlZD8iOiBmYWxzZSwgImFsbG93X2NvZGVfZXhlY3V0aW9u
|
||||
PyI6IGZhbHNlLCAibWF4X3JldHJ5X2xpbWl0IjogMiwgInRvb2xzX25hbWVzIjogW119XUr7AQoK
|
||||
Y3Jld190YXNrcxLsAQrpAVt7ImtleSI6ICIyN2VmMzhjYzk5ZGE0YThkZWQ3MGVkNDA2ZTQ0YWI4
|
||||
NiIsICJpZCI6ICIzOWQzYTIxYi1lMjEwLTRjOTItYWFkMS1kOWFiMzJiN2QwYzgiLCAiYXN5bmNf
|
||||
ZXhlY3V0aW9uPyI6IGZhbHNlLCAiaHVtYW5faW5wdXQ/IjogZmFsc2UsICJhZ2VudF9yb2xlIjog
|
||||
IlNjb3JlciIsICJhZ2VudF9rZXkiOiAiOTJlN2ViMTkxNjY0YzkzNTc4NWVkN2Q0MjQwYTI5NGQi
|
||||
LCAidG9vbHNfbmFtZXMiOiBbXX1degIYAYUBAAEAABKOAgoQEFRUuFJrZGaHfDt3KR9/SBIIGpWv
|
||||
I4OBluIqDFRhc2sgQ3JlYXRlZDABOcOkNbqyoiIYQRVzNrqyoiIYSi4KCGNyZXdfa2V5EiIKIDVl
|
||||
NmVmZmU2ODBhNWQ5N2RjMzg3M2IxNDgyNWNjZmEzSjEKB2NyZXdfaWQSJgokNzhiYmNkY2QtNzVi
|
||||
YS00NzhiLWE5MjctMWYxZGRlMmNjMzljSi4KCHRhc2tfa2V5EiIKIDI3ZWYzOGNjOTlkYTRhOGRl
|
||||
ZDcwZWQ0MDZlNDRhYjg2SjEKB3Rhc2tfaWQSJgokMzlkM2EyMWItZTIxMC00YzkyLWFhZDEtZDlh
|
||||
YjMyYjdkMGM4egIYAYUBAAEAABKdBwoQU+j8yuUwPvUmIZ87Rdy2CRIIBVITP2cxMQ0qDENyZXcg
|
||||
Q3JlYXRlZDABOVdqBLyyoiIYQTLoEryyoiIYShoKDmNyZXdhaV92ZXJzaW9uEggKBjAuODYuMEoa
|
||||
Cg5weXRob25fdmVyc2lvbhIICgYzLjEyLjdKLgoIY3Jld19rZXkSIgogNWU2ZWZmZTY4MGE1ZDk3
|
||||
ZGMzODczYjE0ODI1Y2NmYTNKMQoHY3Jld19pZBImCiQ0NmY2ZmRlOC1kNmNkLTQzZmMtYTc0NS1j
|
||||
MDNhY2I3Y2U2MTBKHgoMY3Jld19wcm9jZXNzEg4KDGhpZXJhcmNoaWNhbEoRCgtjcmV3X21lbW9y
|
||||
eRICEABKGgoUY3Jld19udW1iZXJfb2ZfdGFza3MSAhgBShsKFWNyZXdfbnVtYmVyX29mX2FnZW50
|
||||
cxICGAFKzQIKC2NyZXdfYWdlbnRzEr0CCroCW3sia2V5IjogIjkyZTdlYjE5MTY2NGM5MzU3ODVl
|
||||
ZDdkNDI0MGEyOTRkIiwgImlkIjogIjg2YTRmYTc0LWY0NjItNGYxMS1iMjgwLTg2NDg3MGIxNWI0
|
||||
OSIsICJyb2xlIjogIlNjb3JlciIsICJ2ZXJib3NlPyI6IGZhbHNlLCAibWF4X2l0ZXIiOiAyMCwg
|
||||
Im1heF9ycG0iOiBudWxsLCAiZnVuY3Rpb25fY2FsbGluZ19sbG0iOiAiIiwgImxsbSI6ICJncHQt
|
||||
NG8tbWluaSIsICJkZWxlZ2F0aW9uX2VuYWJsZWQ/IjogZmFsc2UsICJhbGxvd19jb2RlX2V4ZWN1
|
||||
dGlvbj8iOiBmYWxzZSwgIm1heF9yZXRyeV9saW1pdCI6IDIsICJ0b29sc19uYW1lcyI6IFtdfV1K
|
||||
+wEKCmNyZXdfdGFza3MS7AEK6QFbeyJrZXkiOiAiMjdlZjM4Y2M5OWRhNGE4ZGVkNzBlZDQwNmU0
|
||||
NGFiODYiLCAiaWQiOiAiMDkyYTZlMDAtOWMzZi00MTUyLWI3OTQtOWZjZWEzMWU5MjhkIiwgImFz
|
||||
eW5jX2V4ZWN1dGlvbj8iOiBmYWxzZSwgImh1bWFuX2lucHV0PyI6IGZhbHNlLCAiYWdlbnRfcm9s
|
||||
ZSI6ICJTY29yZXIiLCAiYWdlbnRfa2V5IjogIjkyZTdlYjE5MTY2NGM5MzU3ODVlZDdkNDI0MGEy
|
||||
OTRkIiwgInRvb2xzX25hbWVzIjogW119XXoCGAGFAQABAAASjgIKEF2rw4yWEdgHO2kGzCiLUoQS
|
||||
CIg9ai6y1oPuKgxUYXNrIENyZWF0ZWQwATmF3lq8sqIiGEHjs1u8sqIiGEouCghjcmV3X2tleRIi
|
||||
CiA1ZTZlZmZlNjgwYTVkOTdkYzM4NzNiMTQ4MjVjY2ZhM0oxCgdjcmV3X2lkEiYKJDQ2ZjZmZGU4
|
||||
LWQ2Y2QtNDNmYy1hNzQ1LWMwM2FjYjdjZTYxMEouCgh0YXNrX2tleRIiCiAyN2VmMzhjYzk5ZGE0
|
||||
YThkZWQ3MGVkNDA2ZTQ0YWI4NkoxCgd0YXNrX2lkEiYKJDA5MmE2ZTAwLTljM2YtNDE1Mi1iNzk0
|
||||
LTlmY2VhMzFlOTI4ZHoCGAGFAQABAAASnAEKEAN36KhRe3ta38Dk3ahR2FwSCNxUWTBdBaDsKgpU
|
||||
b29sIFVzYWdlMAE5PJ9cvbKiIhhBR1RovbKiIhhKGgoOY3Jld2FpX3ZlcnNpb24SCAoGMC44Ni4w
|
||||
SigKCXRvb2xfbmFtZRIbChlEZWxlZ2F0ZSB3b3JrIHRvIGNvd29ya2VySg4KCGF0dGVtcHRzEgIY
|
||||
AXoCGAGFAQABAAASmwcKEFpDgoyYlY/DBU2f+pRMkuQSCPw+U9k8saIKKgxDcmV3IENyZWF0ZWQw
|
||||
ATnZs+W+sqIiGEHcMPO+sqIiGEoaCg5jcmV3YWlfdmVyc2lvbhIICgYwLjg2LjBKGgoOcHl0aG9u
|
||||
X3ZlcnNpb24SCAoGMy4xMi43Si4KCGNyZXdfa2V5EiIKIDVlNmVmZmU2ODBhNWQ5N2RjMzg3M2Ix
|
||||
NDgyNWNjZmEzSjEKB2NyZXdfaWQSJgokYmMzZjM1MDQtMjBmZC00NjBkLWI0NzQtMWJjNzZjZDBk
|
||||
MGUzShwKDGNyZXdfcHJvY2VzcxIMCgpzZXF1ZW50aWFsShEKC2NyZXdfbWVtb3J5EgIQAEoaChRj
|
||||
cmV3X251bWJlcl9vZl90YXNrcxICGAFKGwoVY3Jld19udW1iZXJfb2ZfYWdlbnRzEgIYAUrNAgoL
|
||||
Y3Jld19hZ2VudHMSvQIKugJbeyJrZXkiOiAiOTJlN2ViMTkxNjY0YzkzNTc4NWVkN2Q0MjQwYTI5
|
||||
NGQiLCAiaWQiOiAiOTU0NjI1ZmEtNTJhNC00Y2VmLWI3MWQtOWZiZTJjYTA3ZTU5IiwgInJvbGUi
|
||||
OiAiU2NvcmVyIiwgInZlcmJvc2U/IjogZmFsc2UsICJtYXhfaXRlciI6IDIwLCAibWF4X3JwbSI6
|
||||
IG51bGwsICJmdW5jdGlvbl9jYWxsaW5nX2xsbSI6ICIiLCAibGxtIjogImdwdC00by1taW5pIiwg
|
||||
ImRlbGVnYXRpb25fZW5hYmxlZD8iOiBmYWxzZSwgImFsbG93X2NvZGVfZXhlY3V0aW9uPyI6IGZh
|
||||
bHNlLCAibWF4X3JldHJ5X2xpbWl0IjogMiwgInRvb2xzX25hbWVzIjogW119XUr7AQoKY3Jld190
|
||||
YXNrcxLsAQrpAVt7ImtleSI6ICIyN2VmMzhjYzk5ZGE0YThkZWQ3MGVkNDA2ZTQ0YWI4NiIsICJp
|
||||
ZCI6ICJiNDQ2ZWZlYS0xZjc5LTQwZjAtYjg4YS1kODJlOWEzN2IwY2EiLCAiYXN5bmNfZXhlY3V0
|
||||
aW9uPyI6IGZhbHNlLCAiaHVtYW5faW5wdXQ/IjogZmFsc2UsICJhZ2VudF9yb2xlIjogIlNjb3Jl
|
||||
ciIsICJhZ2VudF9rZXkiOiAiOTJlN2ViMTkxNjY0YzkzNTc4NWVkN2Q0MjQwYTI5NGQiLCAidG9v
|
||||
bHNfbmFtZXMiOiBbXX1degIYAYUBAAEAABKOAgoQGrXmtpzWVyAIauwYCtnBCRIIPFm96MESP1Qq
|
||||
DFRhc2sgQ3JlYXRlZDABOU4PFb+yoiIYQffRFb+yoiIYSi4KCGNyZXdfa2V5EiIKIDVlNmVmZmU2
|
||||
ODBhNWQ5N2RjMzg3M2IxNDgyNWNjZmEzSjEKB2NyZXdfaWQSJgokYmMzZjM1MDQtMjBmZC00NjBk
|
||||
LWI0NzQtMWJjNzZjZDBkMGUzSi4KCHRhc2tfa2V5EiIKIDI3ZWYzOGNjOTlkYTRhOGRlZDcwZWQ0
|
||||
MDZlNDRhYjg2SjEKB3Rhc2tfaWQSJgokYjQ0NmVmZWEtMWY3OS00MGYwLWI4OGEtZDgyZTlhMzdi
|
||||
MGNhegIYAYUBAAEAABKdBwoQH4jtZY04g9ZJYAFu1vcg4BII0NO+IyC6DoMqDENyZXcgQ3JlYXRl
|
||||
ZDABOSNXssCyoiIYQWoiw8CyoiIYShoKDmNyZXdhaV92ZXJzaW9uEggKBjAuODYuMEoaCg5weXRo
|
||||
b25fdmVyc2lvbhIICgYzLjEyLjdKLgoIY3Jld19rZXkSIgogNWU2ZWZmZTY4MGE1ZDk3ZGMzODcz
|
||||
YjE0ODI1Y2NmYTNKMQoHY3Jld19pZBImCiRlODU1MzU0MC0zYjUyLTQ5N2QtYjUzOS04ZGMxM2M0
|
||||
ZmViNTNKHgoMY3Jld19wcm9jZXNzEg4KDGhpZXJhcmNoaWNhbEoRCgtjcmV3X21lbW9yeRICEABK
|
||||
GgoUY3Jld19udW1iZXJfb2ZfdGFza3MSAhgBShsKFWNyZXdfbnVtYmVyX29mX2FnZW50cxICGAFK
|
||||
zQIKC2NyZXdfYWdlbnRzEr0CCroCW3sia2V5IjogIjkyZTdlYjE5MTY2NGM5MzU3ODVlZDdkNDI0
|
||||
MGEyOTRkIiwgImlkIjogIjdiZWE0ZTkxLWYxMmItNDgwMi04NjQxLWRkOGUyY2Q3NzExZSIsICJy
|
||||
b2xlIjogIlNjb3JlciIsICJ2ZXJib3NlPyI6IGZhbHNlLCAibWF4X2l0ZXIiOiAyMCwgIm1heF9y
|
||||
cG0iOiBudWxsLCAiZnVuY3Rpb25fY2FsbGluZ19sbG0iOiAiIiwgImxsbSI6ICJncHQtNG8tbWlu
|
||||
aSIsICJkZWxlZ2F0aW9uX2VuYWJsZWQ/IjogZmFsc2UsICJhbGxvd19jb2RlX2V4ZWN1dGlvbj8i
|
||||
OiBmYWxzZSwgIm1heF9yZXRyeV9saW1pdCI6IDIsICJ0b29sc19uYW1lcyI6IFtdfV1K+wEKCmNy
|
||||
ZXdfdGFza3MS7AEK6QFbeyJrZXkiOiAiMjdlZjM4Y2M5OWRhNGE4ZGVkNzBlZDQwNmU0NGFiODYi
|
||||
LCAiaWQiOiAiMjcxNGY3YjQtYWJiOC00MmM2LWI2MzQtNDA0YTc2MWRlM2YzIiwgImFzeW5jX2V4
|
||||
ZWN1dGlvbj8iOiBmYWxzZSwgImh1bWFuX2lucHV0PyI6IGZhbHNlLCAiYWdlbnRfcm9sZSI6ICJT
|
||||
Y29yZXIiLCAiYWdlbnRfa2V5IjogIjkyZTdlYjE5MTY2NGM5MzU3ODVlZDdkNDI0MGEyOTRkIiwg
|
||||
InRvb2xzX25hbWVzIjogW119XXoCGAGFAQABAAASjgIKEPBYCb8o50OflufE4VM35GISCHGjIiUy
|
||||
LtjYKgxUYXNrIENyZWF0ZWQwATmf9gHBsqIiGEGPtwLBsqIiGEouCghjcmV3X2tleRIiCiA1ZTZl
|
||||
ZmZlNjgwYTVkOTdkYzM4NzNiMTQ4MjVjY2ZhM0oxCgdjcmV3X2lkEiYKJGU4NTUzNTQwLTNiNTIt
|
||||
NDk3ZC1iNTM5LThkYzEzYzRmZWI1M0ouCgh0YXNrX2tleRIiCiAyN2VmMzhjYzk5ZGE0YThkZWQ3
|
||||
MGVkNDA2ZTQ0YWI4NkoxCgd0YXNrX2lkEiYKJDI3MTRmN2I0LWFiYjgtNDJjNi1iNjM0LTQwNGE3
|
||||
NjFkZTNmM3oCGAGFAQABAAASmwEKEFHngpUVJI31lug7IgEgm7MSCKB9vA0QH8a/KgpUb29sIFVz
|
||||
YWdlMAE562sGwrKiIhhBnGQTwrKiIhhKGgoOY3Jld2FpX3ZlcnNpb24SCAoGMC44Ni4wSicKCXRv
|
||||
b2xfbmFtZRIaChhBc2sgcXVlc3Rpb24gdG8gY293b3JrZXJKDgoIYXR0ZW1wdHMSAhgBegIYAYUB
|
||||
AAEAABKbBwoQn0waYyaXrSNMTDqAV0eGLhIIceVIWp2XUt8qDENyZXcgQ3JlYXRlZDABORQSy8Oy
|
||||
oiIYQSW928OyoiIYShoKDmNyZXdhaV92ZXJzaW9uEggKBjAuODYuMEoaCg5weXRob25fdmVyc2lv
|
||||
bhIICgYzLjEyLjdKLgoIY3Jld19rZXkSIgogNWU2ZWZmZTY4MGE1ZDk3ZGMzODczYjE0ODI1Y2Nm
|
||||
YTNKMQoHY3Jld19pZBImCiQ4ODY5OTRiOC1hYzdhLTRlNmYtYWFhNy0xMzA2Y2E1YjQ2OTNKHAoM
|
||||
Y3Jld19wcm9jZXNzEgwKCnNlcXVlbnRpYWxKEQoLY3Jld19tZW1vcnkSAhAAShoKFGNyZXdfbnVt
|
||||
YmVyX29mX3Rhc2tzEgIYAUobChVjcmV3X251bWJlcl9vZl9hZ2VudHMSAhgBSs0CCgtjcmV3X2Fn
|
||||
ZW50cxK9Agq6Alt7ImtleSI6ICI5MmU3ZWIxOTE2NjRjOTM1Nzg1ZWQ3ZDQyNDBhMjk0ZCIsICJp
|
||||
ZCI6ICJiODZmYjA0Ny05OGViLTQzYTctYTQ3OC00MjE5MTI0NjhkNjkiLCAicm9sZSI6ICJTY29y
|
||||
ZXIiLCAidmVyYm9zZT8iOiBmYWxzZSwgIm1heF9pdGVyIjogMjAsICJtYXhfcnBtIjogbnVsbCwg
|
||||
ImZ1bmN0aW9uX2NhbGxpbmdfbGxtIjogIiIsICJsbG0iOiAiZ3B0LTRvLW1pbmkiLCAiZGVsZWdh
|
||||
dGlvbl9lbmFibGVkPyI6IGZhbHNlLCAiYWxsb3dfY29kZV9leGVjdXRpb24/IjogZmFsc2UsICJt
|
||||
YXhfcmV0cnlfbGltaXQiOiAyLCAidG9vbHNfbmFtZXMiOiBbXX1dSvsBCgpjcmV3X3Rhc2tzEuwB
|
||||
CukBW3sia2V5IjogIjI3ZWYzOGNjOTlkYTRhOGRlZDcwZWQ0MDZlNDRhYjg2IiwgImlkIjogIjZm
|
||||
NTU1NzkzLTgyNTYtNGZiYy05NGFlLTVhOTM3Yzk4NzM4NyIsICJhc3luY19leGVjdXRpb24/Ijog
|
||||
ZmFsc2UsICJodW1hbl9pbnB1dD8iOiBmYWxzZSwgImFnZW50X3JvbGUiOiAiU2NvcmVyIiwgImFn
|
||||
ZW50X2tleSI6ICI5MmU3ZWIxOTE2NjRjOTM1Nzg1ZWQ3ZDQyNDBhMjk0ZCIsICJ0b29sc19uYW1l
|
||||
cyI6IFtdfV16AhgBhQEAAQAAEo4CChBWUygUhVRr+XTD9JGcayMxEghnKkSkqTuRLioMVGFzayBD
|
||||
cmVhdGVkMAE5TMgHxLKiIhhBqp0IxLKiIhhKLgoIY3Jld19rZXkSIgogNWU2ZWZmZTY4MGE1ZDk3
|
||||
ZGMzODczYjE0ODI1Y2NmYTNKMQoHY3Jld19pZBImCiQ4ODY5OTRiOC1hYzdhLTRlNmYtYWFhNy0x
|
||||
MzA2Y2E1YjQ2OTNKLgoIdGFza19rZXkSIgogMjdlZjM4Y2M5OWRhNGE4ZGVkNzBlZDQwNmU0NGFi
|
||||
ODZKMQoHdGFza19pZBImCiQ2ZjU1NTc5My04MjU2LTRmYmMtOTRhZS01YTkzN2M5ODczODd6AhgB
|
||||
hQEAAQAAEpsHChAq8KIQQ3E7AeMax61jSdM/EghVcYH1R/7GSCoMQ3JldyBDcmVhdGVkMAE54tKk
|
||||
xbKiIhhBZiSzxbKiIhhKGgoOY3Jld2FpX3ZlcnNpb24SCAoGMC44Ni4wShoKDnB5dGhvbl92ZXJz
|
||||
aW9uEggKBjMuMTIuN0ouCghjcmV3X2tleRIiCiA1ZTZlZmZlNjgwYTVkOTdkYzM4NzNiMTQ4MjVj
|
||||
Y2ZhM0oxCgdjcmV3X2lkEiYKJGNiOWI5ZWYzLWI0NGItNGUzYy1hZTkyLTA0MTFlYjE0ZTI0Ykoc
|
||||
CgxjcmV3X3Byb2Nlc3MSDAoKc2VxdWVudGlhbEoRCgtjcmV3X21lbW9yeRICEABKGgoUY3Jld19u
|
||||
dW1iZXJfb2ZfdGFza3MSAhgBShsKFWNyZXdfbnVtYmVyX29mX2FnZW50cxICGAFKzQIKC2NyZXdf
|
||||
YWdlbnRzEr0CCroCW3sia2V5IjogIjkyZTdlYjE5MTY2NGM5MzU3ODVlZDdkNDI0MGEyOTRkIiwg
|
||||
ImlkIjogIjU4OWU2ZGM2LWI4NzYtNGVmOS1iNDI4LTY2YzA0N2I0YjdiYSIsICJyb2xlIjogIlNj
|
||||
b3JlciIsICJ2ZXJib3NlPyI6IGZhbHNlLCAibWF4X2l0ZXIiOiAyMCwgIm1heF9ycG0iOiBudWxs
|
||||
LCAiZnVuY3Rpb25fY2FsbGluZ19sbG0iOiAiIiwgImxsbSI6ICJncHQtNG8tbWluaSIsICJkZWxl
|
||||
Z2F0aW9uX2VuYWJsZWQ/IjogZmFsc2UsICJhbGxvd19jb2RlX2V4ZWN1dGlvbj8iOiBmYWxzZSwg
|
||||
Im1heF9yZXRyeV9saW1pdCI6IDIsICJ0b29sc19uYW1lcyI6IFtdfV1K+wEKCmNyZXdfdGFza3MS
|
||||
7AEK6QFbeyJrZXkiOiAiMjdlZjM4Y2M5OWRhNGE4ZGVkNzBlZDQwNmU0NGFiODYiLCAiaWQiOiAi
|
||||
ZmUxM2Q5YjktYTQxNS00MjM2LWE3MGUtYTljZjc0Zjg3MzlkIiwgImFzeW5jX2V4ZWN1dGlvbj8i
|
||||
OiBmYWxzZSwgImh1bWFuX2lucHV0PyI6IGZhbHNlLCAiYWdlbnRfcm9sZSI6ICJTY29yZXIiLCAi
|
||||
YWdlbnRfa2V5IjogIjkyZTdlYjE5MTY2NGM5MzU3ODVlZDdkNDI0MGEyOTRkIiwgInRvb2xzX25h
|
||||
bWVzIjogW119XXoCGAGFAQABAAASjgIKENMEGj/C5i4cl9DUwZUNpKISCE3/r9XA1v+iKgxUYXNr
|
||||
IENyZWF0ZWQwATnX3NTFsqIiGEEDp9jFsqIiGEouCghjcmV3X2tleRIiCiA1ZTZlZmZlNjgwYTVk
|
||||
OTdkYzM4NzNiMTQ4MjVjY2ZhM0oxCgdjcmV3X2lkEiYKJGNiOWI5ZWYzLWI0NGItNGUzYy1hZTky
|
||||
LTA0MTFlYjE0ZTI0YkouCgh0YXNrX2tleRIiCiAyN2VmMzhjYzk5ZGE0YThkZWQ3MGVkNDA2ZTQ0
|
||||
YWI4NkoxCgd0YXNrX2lkEiYKJGZlMTNkOWI5LWE0MTUtNDIzNi1hNzBlLWE5Y2Y3NGY4NzM5ZHoC
|
||||
GAGFAQABAAASnQcKEP/Rj1V9+WGy0TFG8X4SbtsSCKeG55Fgl+O0KgxDcmV3IENyZWF0ZWQwATkT
|
||||
pXXHsqIiGEFqDIXHsqIiGEoaCg5jcmV3YWlfdmVyc2lvbhIICgYwLjg2LjBKGgoOcHl0aG9uX3Zl
|
||||
cnNpb24SCAoGMy4xMi43Si4KCGNyZXdfa2V5EiIKIDVlNmVmZmU2ODBhNWQ5N2RjMzg3M2IxNDgy
|
||||
NWNjZmEzSjEKB2NyZXdfaWQSJgokODJhNjVhMmItOTY1My00NjRhLThmMWMtYmRkNDAwOTEzOGJl
|
||||
Sh4KDGNyZXdfcHJvY2VzcxIOCgxoaWVyYXJjaGljYWxKEQoLY3Jld19tZW1vcnkSAhAAShoKFGNy
|
||||
ZXdfbnVtYmVyX29mX3Rhc2tzEgIYAUobChVjcmV3X251bWJlcl9vZl9hZ2VudHMSAhgBSs0CCgtj
|
||||
cmV3X2FnZW50cxK9Agq6Alt7ImtleSI6ICI5MmU3ZWIxOTE2NjRjOTM1Nzg1ZWQ3ZDQyNDBhMjk0
|
||||
ZCIsICJpZCI6ICIxZWVjNzE3Yi1mNjA3LTRhMWEtYTJjZC00YWZkYjUzMTE4YjYiLCAicm9sZSI6
|
||||
ICJTY29yZXIiLCAidmVyYm9zZT8iOiBmYWxzZSwgIm1heF9pdGVyIjogMjAsICJtYXhfcnBtIjog
|
||||
bnVsbCwgImZ1bmN0aW9uX2NhbGxpbmdfbGxtIjogIiIsICJsbG0iOiAiZ3B0LTRvLW1pbmkiLCAi
|
||||
ZGVsZWdhdGlvbl9lbmFibGVkPyI6IGZhbHNlLCAiYWxsb3dfY29kZV9leGVjdXRpb24/IjogZmFs
|
||||
c2UsICJtYXhfcmV0cnlfbGltaXQiOiAyLCAidG9vbHNfbmFtZXMiOiBbXX1dSvsBCgpjcmV3X3Rh
|
||||
c2tzEuwBCukBW3sia2V5IjogIjI3ZWYzOGNjOTlkYTRhOGRlZDcwZWQ0MDZlNDRhYjg2IiwgImlk
|
||||
IjogIjc4MzVkZGI2LTE2MzQtNGRjOC05NTU2LWNjY2I5YzEzY2MwNiIsICJhc3luY19leGVjdXRp
|
||||
b24/IjogZmFsc2UsICJodW1hbl9pbnB1dD8iOiBmYWxzZSwgImFnZW50X3JvbGUiOiAiU2NvcmVy
|
||||
IiwgImFnZW50X2tleSI6ICI5MmU3ZWIxOTE2NjRjOTM1Nzg1ZWQ3ZDQyNDBhMjk0ZCIsICJ0b29s
|
||||
c19uYW1lcyI6IFtdfV16AhgBhQEAAQAAEo4CChCFFtDnDWcsSudUWbwW4eLiEgi4LAp7OG8lqSoM
|
||||
VGFzayBDcmVhdGVkMAE5YvW/x7KiIhhBqcXAx7KiIhhKLgoIY3Jld19rZXkSIgogNWU2ZWZmZTY4
|
||||
MGE1ZDk3ZGMzODczYjE0ODI1Y2NmYTNKMQoHY3Jld19pZBImCiQ4MmE2NWEyYi05NjUzLTQ2NGEt
|
||||
OGYxYy1iZGQ0MDA5MTM4YmVKLgoIdGFza19rZXkSIgogMjdlZjM4Y2M5OWRhNGE4ZGVkNzBlZDQw
|
||||
NmU0NGFiODZKMQoHdGFza19pZBImCiQ3ODM1ZGRiNi0xNjM0LTRkYzgtOTU1Ni1jY2NiOWMxM2Nj
|
||||
MDZ6AhgBhQEAAQAAEpsBChC3Ppb3mHQknnMrEMfb/V/UEghlgq67xv6tdyoKVG9vbCBVc2FnZTAB
|
||||
Oafq4siyoiIYQUM578iyoiIYShoKDmNyZXdhaV92ZXJzaW9uEggKBjAuODYuMEonCgl0b29sX25h
|
||||
bWUSGgoYQXNrIHF1ZXN0aW9uIHRvIGNvd29ya2VySg4KCGF0dGVtcHRzEgIYAXoCGAGFAQABAAAS
|
||||
nAkKEOiarXK28LHI5ABYZaMQR0oSCIkXl7b6Uyz2KgxDcmV3IENyZWF0ZWQwATmZbbvKsqIiGEGk
|
||||
o8nKsqIiGEoaCg5jcmV3YWlfdmVyc2lvbhIICgYwLjg2LjBKGgoOcHl0aG9uX3ZlcnNpb24SCAoG
|
||||
My4xMi43Si4KCGNyZXdfa2V5EiIKIGQ0MjYwODMzYWIwYzIwYmI0NDkyMmM3OTlhYTk2YjRhSjEK
|
||||
B2NyZXdfaWQSJgokYzE1OTEzNGQtZmRkNC00ODM2LWI5MjUtZTk1ZmY5MDY0OTEyShwKDGNyZXdf
|
||||
cHJvY2VzcxIMCgpzZXF1ZW50aWFsShEKC2NyZXdfbWVtb3J5EgIQAEoaChRjcmV3X251bWJlcl9v
|
||||
Zl90YXNrcxICGAJKGwoVY3Jld19udW1iZXJfb2ZfYWdlbnRzEgIYAUrlAgoLY3Jld19hZ2VudHMS
|
||||
1QIK0gJbeyJrZXkiOiAiOTJlN2ViMTkxNjY0YzkzNTc4NWVkN2Q0MjQwYTI5NGQiLCAiaWQiOiAi
|
||||
YWI2NGVkZjYtN2JkOC00MWFhLWI3OGYtMzY0OWE5MjkxZjE2IiwgInJvbGUiOiAiU2NvcmVyIiwg
|
||||
InZlcmJvc2U/IjogdHJ1ZSwgIm1heF9pdGVyIjogMjAsICJtYXhfcnBtIjogbnVsbCwgImZ1bmN0
|
||||
aW9uX2NhbGxpbmdfbGxtIjogImdwdC0zLjUtdHVyYm8tMDEyNSIsICJsbG0iOiAiZ3B0LTQtMDEy
|
||||
NS1wcmV2aWV3IiwgImRlbGVnYXRpb25fZW5hYmxlZD8iOiBmYWxzZSwgImFsbG93X2NvZGVfZXhl
|
||||
Y3V0aW9uPyI6IGZhbHNlLCAibWF4X3JldHJ5X2xpbWl0IjogMiwgInRvb2xzX25hbWVzIjogW119
|
||||
XUrkAwoKY3Jld190YXNrcxLVAwrSA1t7ImtleSI6ICIyN2VmMzhjYzk5ZGE0YThkZWQ3MGVkNDA2
|
||||
ZTQ0YWI4NiIsICJpZCI6ICIzZmQ2MThmOC1mZGM5LTQ0ZGQtYTQyNi0xMGU5MjFjOGU5ZWUiLCAi
|
||||
YXN5bmNfZXhlY3V0aW9uPyI6IGZhbHNlLCAiaHVtYW5faW5wdXQ/IjogZmFsc2UsICJhZ2VudF9y
|
||||
b2xlIjogIlNjb3JlciIsICJhZ2VudF9rZXkiOiAiOTJlN2ViMTkxNjY0YzkzNTc4NWVkN2Q0MjQw
|
||||
YTI5NGQiLCAidG9vbHNfbmFtZXMiOiBbXX0sIHsia2V5IjogIjYwOWRlZTM5MTA4OGNkMWM4N2I4
|
||||
ZmE2NmFhNjdhZGJlIiwgImlkIjogIjM0YzRmMDdmLWQ5YzMtNDg0Mi1hNjg4LWUwZGI4MmI0M2M4
|
||||
YiIsICJhc3luY19leGVjdXRpb24/IjogZmFsc2UsICJodW1hbl9pbnB1dD8iOiBmYWxzZSwgImFn
|
||||
ZW50X3JvbGUiOiAiU2NvcmVyIiwgImFnZW50X2tleSI6ICI5MmU3ZWIxOTE2NjRjOTM1Nzg1ZWQ3
|
||||
ZDQyNDBhMjk0ZCIsICJ0b29sc19uYW1lcyI6IFtdfV16AhgBhQEAAQAAEo4CChASxgUnYtTYTxXF
|
||||
XZo7SOOoEghgeOK3dYXmFyoMVGFzayBDcmVhdGVkMAE5PBfsyrKiIhhBrXTtyrKiIhhKLgoIY3Jl
|
||||
d19rZXkSIgogZDQyNjA4MzNhYjBjMjBiYjQ0OTIyYzc5OWFhOTZiNGFKMQoHY3Jld19pZBImCiRj
|
||||
MTU5MTM0ZC1mZGQ0LTQ4MzYtYjkyNS1lOTVmZjkwNjQ5MTJKLgoIdGFza19rZXkSIgogMjdlZjM4
|
||||
Y2M5OWRhNGE4ZGVkNzBlZDQwNmU0NGFiODZKMQoHdGFza19pZBImCiQzZmQ2MThmOC1mZGM5LTQ0
|
||||
ZGQtYTQyNi0xMGU5MjFjOGU5ZWV6AhgBhQEAAQAAEo4CChB9aJKgUXFcp/D+2ZFIZYGxEgin8KsA
|
||||
V2c/kyoMVGFzayBDcmVhdGVkMAE5KfT7y7KiIhhBguf8y7KiIhhKLgoIY3Jld19rZXkSIgogZDQy
|
||||
NjA4MzNhYjBjMjBiYjQ0OTIyYzc5OWFhOTZiNGFKMQoHY3Jld19pZBImCiRjMTU5MTM0ZC1mZGQ0
|
||||
LTQ4MzYtYjkyNS1lOTVmZjkwNjQ5MTJKLgoIdGFza19rZXkSIgogNjA5ZGVlMzkxMDg4Y2QxYzg3
|
||||
YjhmYTY2YWE2N2FkYmVKMQoHdGFza19pZBImCiQzNGM0ZjA3Zi1kOWMzLTQ4NDItYTY4OC1lMGRi
|
||||
ODJiNDNjOGJ6AhgBhQEAAQAAEoQJChAZep02+oI5yaAkv2xZqLuREghN4M46C6n0/yoMQ3JldyBD
|
||||
cmVhdGVkMAE5G/epzbKiIhhBHWW4zbKiIhhKGgoOY3Jld2FpX3ZlcnNpb24SCAoGMC44Ni4wShoK
|
||||
DnB5dGhvbl92ZXJzaW9uEggKBjMuMTIuN0ouCghjcmV3X2tleRIiCiBhOTU0MGNkMGVhYTUzZjY3
|
||||
NTQzN2U5YmQ0ZmE1ZTQ0Y0oxCgdjcmV3X2lkEiYKJDU5NmI2NjJiLWMxY2QtNDk0Yi1hZjBmLWUw
|
||||
ZWY4ODRhNjc1MUocCgxjcmV3X3Byb2Nlc3MSDAoKc2VxdWVudGlhbEoRCgtjcmV3X21lbW9yeRIC
|
||||
EABKGgoUY3Jld19udW1iZXJfb2ZfdGFza3MSAhgCShsKFWNyZXdfbnVtYmVyX29mX2FnZW50cxIC
|
||||
GAFKzQIKC2NyZXdfYWdlbnRzEr0CCroCW3sia2V5IjogIjkyZTdlYjE5MTY2NGM5MzU3ODVlZDdk
|
||||
NDI0MGEyOTRkIiwgImlkIjogIjRkZmNhNDNmLTlhNDYtNDZmMy1hMzNjLTJhN2NmMjRmODg5ZSIs
|
||||
ICJyb2xlIjogIlNjb3JlciIsICJ2ZXJib3NlPyI6IGZhbHNlLCAibWF4X2l0ZXIiOiAyMCwgIm1h
|
||||
eF9ycG0iOiBudWxsLCAiZnVuY3Rpb25fY2FsbGluZ19sbG0iOiAiIiwgImxsbSI6ICJncHQtNG8t
|
||||
bWluaSIsICJkZWxlZ2F0aW9uX2VuYWJsZWQ/IjogZmFsc2UsICJhbGxvd19jb2RlX2V4ZWN1dGlv
|
||||
bj8iOiBmYWxzZSwgIm1heF9yZXRyeV9saW1pdCI6IDIsICJ0b29sc19uYW1lcyI6IFtdfV1K5AMK
|
||||
CmNyZXdfdGFza3MS1QMK0gNbeyJrZXkiOiAiMjdlZjM4Y2M5OWRhNGE4ZGVkNzBlZDQwNmU0NGFi
|
||||
ODYiLCAiaWQiOiAiOTJhYTgwM2QtODI2YS00ZGMyLThhNjMtYWJiMWE0Mzg0NThjIiwgImFzeW5j
|
||||
X2V4ZWN1dGlvbj8iOiBmYWxzZSwgImh1bWFuX2lucHV0PyI6IGZhbHNlLCAiYWdlbnRfcm9sZSI6
|
||||
ICJTY29yZXIiLCAiYWdlbnRfa2V5IjogIjkyZTdlYjE5MTY2NGM5MzU3ODVlZDdkNDI0MGEyOTRk
|
||||
IiwgInRvb2xzX25hbWVzIjogW119LCB7ImtleSI6ICJiMGQzNGE2ZjYyMWE3YjM1ODBkNWQxZjRl
|
||||
MjY2NWI5MiIsICJpZCI6ICIyZWU0NjZjZC1lYWU1LTQwMzYtOWYwYS0xMDdlZGNiMDNkNGEiLCAi
|
||||
YXN5bmNfZXhlY3V0aW9uPyI6IGZhbHNlLCAiaHVtYW5faW5wdXQ/IjogZmFsc2UsICJhZ2VudF9y
|
||||
b2xlIjogIlNjb3JlciIsICJhZ2VudF9rZXkiOiAiOTJlN2ViMTkxNjY0YzkzNTc4NWVkN2Q0MjQw
|
||||
YTI5NGQiLCAidG9vbHNfbmFtZXMiOiBbXX1degIYAYUBAAEAABKOAgoQuipO56JB6yIRwQuBkZLU
|
||||
KRIIb2SQdlh6MPYqDFRhc2sgQ3JlYXRlZDABOcVi3s2yoiIYQTFE382yoiIYSi4KCGNyZXdfa2V5
|
||||
EiIKIGE5NTQwY2QwZWFhNTNmNjc1NDM3ZTliZDRmYTVlNDRjSjEKB2NyZXdfaWQSJgokNTk2YjY2
|
||||
MmItYzFjZC00OTRiLWFmMGYtZTBlZjg4NGE2NzUxSi4KCHRhc2tfa2V5EiIKIDI3ZWYzOGNjOTlk
|
||||
YTRhOGRlZDcwZWQ0MDZlNDRhYjg2SjEKB3Rhc2tfaWQSJgokOTJhYTgwM2QtODI2YS00ZGMyLThh
|
||||
NjMtYWJiMWE0Mzg0NThjegIYAYUBAAEAABKOAgoQbt8b/9cQuopXT9Z2BjD/qxIIPKLWhfqZUXkq
|
||||
DFRhc2sgQ3JlYXRlZDABOYjy8s6yoiIYQZ/v886yoiIYSi4KCGNyZXdfa2V5EiIKIGE5NTQwY2Qw
|
||||
ZWFhNTNmNjc1NDM3ZTliZDRmYTVlNDRjSjEKB2NyZXdfaWQSJgokNTk2YjY2MmItYzFjZC00OTRi
|
||||
LWFmMGYtZTBlZjg4NGE2NzUxSi4KCHRhc2tfa2V5EiIKIGIwZDM0YTZmNjIxYTdiMzU4MGQ1ZDFm
|
||||
NGUyNjY1YjkySjEKB3Rhc2tfaWQSJgokMmVlNDY2Y2QtZWFlNS00MDM2LTlmMGEtMTA3ZWRjYjAz
|
||||
ZDRhegIYAYUBAAEAABKbBwoQ2VT10GKkg1d69rZRnFqkhhII4xr+v1CKdekqDENyZXcgQ3JlYXRl
|
||||
ZDABOQpdgtCyoiIYQSR3kNCyoiIYShoKDmNyZXdhaV92ZXJzaW9uEggKBjAuODYuMEoaCg5weXRo
|
||||
b25fdmVyc2lvbhIICgYzLjEyLjdKLgoIY3Jld19rZXkSIgogNWU2ZWZmZTY4MGE1ZDk3ZGMzODcz
|
||||
YjE0ODI1Y2NmYTNKMQoHY3Jld19pZBImCiQzZTFhNzdhMS1lYTljLTQ5OWYtODhkNS0wZmRkNTg5
|
||||
YTA5YWZKHAoMY3Jld19wcm9jZXNzEgwKCnNlcXVlbnRpYWxKEQoLY3Jld19tZW1vcnkSAhAAShoK
|
||||
FGNyZXdfbnVtYmVyX29mX3Rhc2tzEgIYAUobChVjcmV3X251bWJlcl9vZl9hZ2VudHMSAhgBSs0C
|
||||
CgtjcmV3X2FnZW50cxK9Agq6Alt7ImtleSI6ICI5MmU3ZWIxOTE2NjRjOTM1Nzg1ZWQ3ZDQyNDBh
|
||||
Mjk0ZCIsICJpZCI6ICJlZWViNmU2ZS1lN2UxLTQ0MDctODI3MS03N2Y1MTI1OGJiZTciLCAicm9s
|
||||
ZSI6ICJTY29yZXIiLCAidmVyYm9zZT8iOiBmYWxzZSwgIm1heF9pdGVyIjogMjAsICJtYXhfcnBt
|
||||
IjogbnVsbCwgImZ1bmN0aW9uX2NhbGxpbmdfbGxtIjogIiIsICJsbG0iOiAiZ3B0LTRvLW1pbmki
|
||||
LCAiZGVsZWdhdGlvbl9lbmFibGVkPyI6IGZhbHNlLCAiYWxsb3dfY29kZV9leGVjdXRpb24/Ijog
|
||||
ZmFsc2UsICJtYXhfcmV0cnlfbGltaXQiOiAyLCAidG9vbHNfbmFtZXMiOiBbXX1dSvsBCgpjcmV3
|
||||
X3Rhc2tzEuwBCukBW3sia2V5IjogIjI3ZWYzOGNjOTlkYTRhOGRlZDcwZWQ0MDZlNDRhYjg2Iiwg
|
||||
ImlkIjogIjNjNmE0ODE5LWU1YTUtNDlhMS04NDNhLTg5OWU1MjQ2NGZhMCIsICJhc3luY19leGVj
|
||||
dXRpb24/IjogZmFsc2UsICJodW1hbl9pbnB1dD8iOiBmYWxzZSwgImFnZW50X3JvbGUiOiAiU2Nv
|
||||
cmVyIiwgImFnZW50X2tleSI6ICI5MmU3ZWIxOTE2NjRjOTM1Nzg1ZWQ3ZDQyNDBhMjk0ZCIsICJ0
|
||||
b29sc19uYW1lcyI6IFtdfV16AhgBhQEAAQAAEo4CChAv9cAzWupJxutUpthTr0F8Eggdrbb0Fig9
|
||||
hCoMVGFzayBDcmVhdGVkMAE5bpO00LKiIhhBahC20LKiIhhKLgoIY3Jld19rZXkSIgogNWU2ZWZm
|
||||
ZTY4MGE1ZDk3ZGMzODczYjE0ODI1Y2NmYTNKMQoHY3Jld19pZBImCiQzZTFhNzdhMS1lYTljLTQ5
|
||||
OWYtODhkNS0wZmRkNTg5YTA5YWZKLgoIdGFza19rZXkSIgogMjdlZjM4Y2M5OWRhNGE4ZGVkNzBl
|
||||
ZDQwNmU0NGFiODZKMQoHdGFza19pZBImCiQzYzZhNDgxOS1lNWE1LTQ5YTEtODQzYS04OTllNTI0
|
||||
NjRmYTB6AhgBhQEAAQAAEpsHChAv/VGrvX6LpZ5u+VihvlpIEgio1hBboTt+pioMQ3JldyBDcmVh
|
||||
dGVkMAE5Vzm+0bKiIhhBY2vP0bKiIhhKGgoOY3Jld2FpX3ZlcnNpb24SCAoGMC44Ni4wShoKDnB5
|
||||
dGhvbl92ZXJzaW9uEggKBjMuMTIuN0ouCghjcmV3X2tleRIiCiA1ZTZlZmZlNjgwYTVkOTdkYzM4
|
||||
NzNiMTQ4MjVjY2ZhM0oxCgdjcmV3X2lkEiYKJDkyMGNjNTE0LTMwYzctNGJhNC1hYTYxLWY3MDcz
|
||||
ZTFkZDFiMkocCgxjcmV3X3Byb2Nlc3MSDAoKc2VxdWVudGlhbEoRCgtjcmV3X21lbW9yeRICEABK
|
||||
GgoUY3Jld19udW1iZXJfb2ZfdGFza3MSAhgBShsKFWNyZXdfbnVtYmVyX29mX2FnZW50cxICGAFK
|
||||
zQIKC2NyZXdfYWdlbnRzEr0CCroCW3sia2V5IjogIjkyZTdlYjE5MTY2NGM5MzU3ODVlZDdkNDI0
|
||||
MGEyOTRkIiwgImlkIjogImI4MDZmOGI3LThhM2YtNDA5Mi05OTg5LWRiYTNkY2YxYWRmOSIsICJy
|
||||
b2xlIjogIlNjb3JlciIsICJ2ZXJib3NlPyI6IGZhbHNlLCAibWF4X2l0ZXIiOiAyMCwgIm1heF9y
|
||||
cG0iOiBudWxsLCAiZnVuY3Rpb25fY2FsbGluZ19sbG0iOiAiIiwgImxsbSI6ICJncHQtNG8tbWlu
|
||||
aSIsICJkZWxlZ2F0aW9uX2VuYWJsZWQ/IjogZmFsc2UsICJhbGxvd19jb2RlX2V4ZWN1dGlvbj8i
|
||||
OiBmYWxzZSwgIm1heF9yZXRyeV9saW1pdCI6IDIsICJ0b29sc19uYW1lcyI6IFtdfV1K+wEKCmNy
|
||||
ZXdfdGFza3MS7AEK6QFbeyJrZXkiOiAiMjdlZjM4Y2M5OWRhNGE4ZGVkNzBlZDQwNmU0NGFiODYi
|
||||
LCAiaWQiOiAiOWJmZjcxMGUtNDhlMC00YTU4LTkzMzgtYzNkOWZkOGMwMzI2IiwgImFzeW5jX2V4
|
||||
ZWN1dGlvbj8iOiBmYWxzZSwgImh1bWFuX2lucHV0PyI6IGZhbHNlLCAiYWdlbnRfcm9sZSI6ICJT
|
||||
Y29yZXIiLCAiYWdlbnRfa2V5IjogIjkyZTdlYjE5MTY2NGM5MzU3ODVlZDdkNDI0MGEyOTRkIiwg
|
||||
InRvb2xzX25hbWVzIjogW119XXoCGAGFAQABAAASjgIKEMPnJUO4wxrLHSqEtDvdf70SCNSV3q60
|
||||
HIhJKgxUYXNrIENyZWF0ZWQwATltq+/RsqIiGEFUfvDRsqIiGEouCghjcmV3X2tleRIiCiA1ZTZl
|
||||
ZmZlNjgwYTVkOTdkYzM4NzNiMTQ4MjVjY2ZhM0oxCgdjcmV3X2lkEiYKJDkyMGNjNTE0LTMwYzct
|
||||
NGJhNC1hYTYxLWY3MDczZTFkZDFiMkouCgh0YXNrX2tleRIiCiAyN2VmMzhjYzk5ZGE0YThkZWQ3
|
||||
MGVkNDA2ZTQ0YWI4NkoxCgd0YXNrX2lkEiYKJDliZmY3MTBlLTQ4ZTAtNGE1OC05MzM4LWMzZDlm
|
||||
ZDhjMDMyNnoCGAGFAQABAAASmwcKEN1mwgGo2lUwwKWg+sJwL+ASCMg+YQDXv2wfKgxDcmV3IENy
|
||||
ZWF0ZWQwATlQIYjTsqIiGEEgtZbTsqIiGEoaCg5jcmV3YWlfdmVyc2lvbhIICgYwLjg2LjBKGgoO
|
||||
cHl0aG9uX3ZlcnNpb24SCAoGMy4xMi43Si4KCGNyZXdfa2V5EiIKIDVlNmVmZmU2ODBhNWQ5N2Rj
|
||||
Mzg3M2IxNDgyNWNjZmEzSjEKB2NyZXdfaWQSJgokNjBmOTQxMTQtNzE3ZS00MGVhLThjZTAtYjRl
|
||||
MjUwNzg1YWFlShwKDGNyZXdfcHJvY2VzcxIMCgpzZXF1ZW50aWFsShEKC2NyZXdfbWVtb3J5EgIQ
|
||||
AEoaChRjcmV3X251bWJlcl9vZl90YXNrcxICGAFKGwoVY3Jld19udW1iZXJfb2ZfYWdlbnRzEgIY
|
||||
AUrNAgoLY3Jld19hZ2VudHMSvQIKugJbeyJrZXkiOiAiOTJlN2ViMTkxNjY0YzkzNTc4NWVkN2Q0
|
||||
MjQwYTI5NGQiLCAiaWQiOiAiZmYwOTdmZDQtYWUzOC00MjI4LTljNWEtM2UwZGJkMTlkZjM0Iiwg
|
||||
InJvbGUiOiAiU2NvcmVyIiwgInZlcmJvc2U/IjogZmFsc2UsICJtYXhfaXRlciI6IDIwLCAibWF4
|
||||
X3JwbSI6IG51bGwsICJmdW5jdGlvbl9jYWxsaW5nX2xsbSI6ICIiLCAibGxtIjogImdwdC00by1t
|
||||
aW5pIiwgImRlbGVnYXRpb25fZW5hYmxlZD8iOiBmYWxzZSwgImFsbG93X2NvZGVfZXhlY3V0aW9u
|
||||
PyI6IGZhbHNlLCAibWF4X3JldHJ5X2xpbWl0IjogMiwgInRvb2xzX25hbWVzIjogW119XUr7AQoK
|
||||
Y3Jld190YXNrcxLsAQrpAVt7ImtleSI6ICIyN2VmMzhjYzk5ZGE0YThkZWQ3MGVkNDA2ZTQ0YWI4
|
||||
NiIsICJpZCI6ICIxNzc2NDg1Mi0wMDJjLTQ1NGUtYmI0Mi0wNDY4NTgwMzIyOWUiLCAiYXN5bmNf
|
||||
ZXhlY3V0aW9uPyI6IGZhbHNlLCAiaHVtYW5faW5wdXQ/IjogZmFsc2UsICJhZ2VudF9yb2xlIjog
|
||||
IlNjb3JlciIsICJhZ2VudF9rZXkiOiAiOTJlN2ViMTkxNjY0YzkzNTc4NWVkN2Q0MjQwYTI5NGQi
|
||||
LCAidG9vbHNfbmFtZXMiOiBbXX1degIYAYUBAAEAABKOAgoQVD9sog/N7cGJK2BQEk1DDxIIQjom
|
||||
eD+Ctv4qDFRhc2sgQ3JlYXRlZDABOdSUvdOyoiIYQad7vtOyoiIYSi4KCGNyZXdfa2V5EiIKIDVl
|
||||
NmVmZmU2ODBhNWQ5N2RjMzg3M2IxNDgyNWNjZmEzSjEKB2NyZXdfaWQSJgokNjBmOTQxMTQtNzE3
|
||||
ZS00MGVhLThjZTAtYjRlMjUwNzg1YWFlSi4KCHRhc2tfa2V5EiIKIDI3ZWYzOGNjOTlkYTRhOGRl
|
||||
ZDcwZWQ0MDZlNDRhYjg2SjEKB3Rhc2tfaWQSJgokMTc3NjQ4NTItMDAyYy00NTRlLWJiNDItMDQ2
|
||||
ODU4MDMyMjllegIYAYUBAAEAABKbBwoQCNV5wZRaTYL2KDS9wW/hABII9uupLGfh3r0qDENyZXcg
|
||||
Q3JlYXRlZDABOWo1VtWyoiIYQQdaZdWyoiIYShoKDmNyZXdhaV92ZXJzaW9uEggKBjAuODYuMEoa
|
||||
Cg5weXRob25fdmVyc2lvbhIICgYzLjEyLjdKLgoIY3Jld19rZXkSIgogNWU2ZWZmZTY4MGE1ZDk3
|
||||
ZGMzODczYjE0ODI1Y2NmYTNKMQoHY3Jld19pZBImCiQ4OTE1MjY5ZS1iNTk5LTQwZGEtOGU3Yi0z
|
||||
M2Q4ZTBkMDlmOWFKHAoMY3Jld19wcm9jZXNzEgwKCnNlcXVlbnRpYWxKEQoLY3Jld19tZW1vcnkS
|
||||
AhAAShoKFGNyZXdfbnVtYmVyX29mX3Rhc2tzEgIYAUobChVjcmV3X251bWJlcl9vZl9hZ2VudHMS
|
||||
AhgBSs0CCgtjcmV3X2FnZW50cxK9Agq6Alt7ImtleSI6ICI5MmU3ZWIxOTE2NjRjOTM1Nzg1ZWQ3
|
||||
ZDQyNDBhMjk0ZCIsICJpZCI6ICI0NzlhOTJmNC04ZDQ4LTQ4NTktYWZlZi1mMjdhZTU5MjMwOTIi
|
||||
LCAicm9sZSI6ICJTY29yZXIiLCAidmVyYm9zZT8iOiBmYWxzZSwgIm1heF9pdGVyIjogMjAsICJt
|
||||
YXhfcnBtIjogbnVsbCwgImZ1bmN0aW9uX2NhbGxpbmdfbGxtIjogIiIsICJsbG0iOiAiZ3B0LTRv
|
||||
LW1pbmkiLCAiZGVsZWdhdGlvbl9lbmFibGVkPyI6IGZhbHNlLCAiYWxsb3dfY29kZV9leGVjdXRp
|
||||
b24/IjogZmFsc2UsICJtYXhfcmV0cnlfbGltaXQiOiAyLCAidG9vbHNfbmFtZXMiOiBbXX1dSvsB
|
||||
CgpjcmV3X3Rhc2tzEuwBCukBW3sia2V5IjogIjI3ZWYzOGNjOTlkYTRhOGRlZDcwZWQ0MDZlNDRh
|
||||
Yjg2IiwgImlkIjogImM1NWFlOTM4LTIxYmQtNGYxMi1hZmIwLTIyN2I4YWY4NzE5NiIsICJhc3lu
|
||||
Y19leGVjdXRpb24/IjogZmFsc2UsICJodW1hbl9pbnB1dD8iOiBmYWxzZSwgImFnZW50X3JvbGUi
|
||||
OiAiU2NvcmVyIiwgImFnZW50X2tleSI6ICI5MmU3ZWIxOTE2NjRjOTM1Nzg1ZWQ3ZDQyNDBhMjk0
|
||||
ZCIsICJ0b29sc19uYW1lcyI6IFtdfV16AhgBhQEAAQAAEo4CChDtCt/5KBW9Zxn+I3ke1Zf8EgjD
|
||||
2U7Px3YQMSoMVGFzayBDcmVhdGVkMAE50VGI1bKiIhhBI8OJ1bKiIhhKLgoIY3Jld19rZXkSIgog
|
||||
NWU2ZWZmZTY4MGE1ZDk3ZGMzODczYjE0ODI1Y2NmYTNKMQoHY3Jld19pZBImCiQ4OTE1MjY5ZS1i
|
||||
NTk5LTQwZGEtOGU3Yi0zM2Q4ZTBkMDlmOWFKLgoIdGFza19rZXkSIgogMjdlZjM4Y2M5OWRhNGE4
|
||||
ZGVkNzBlZDQwNmU0NGFiODZKMQoHdGFza19pZBImCiRjNTVhZTkzOC0yMWJkLTRmMTItYWZiMC0y
|
||||
MjdiOGFmODcxOTZ6AhgBhQEAAQAAEv0GChBMsOxZ+2or2a1kPcIoexDGEghAM8V42mOfsCoMQ3Jl
|
||||
dyBDcmVhdGVkMAE5GK+c1rKiIhhB9des1rKiIhhKGgoOY3Jld2FpX3ZlcnNpb24SCAoGMC44Ni4w
|
||||
ShoKDnB5dGhvbl92ZXJzaW9uEggKBjMuMTIuN0ouCghjcmV3X2tleRIiCiA1ZTZlZmZlNjgwYTVk
|
||||
OTdkYzM4NzNiMTQ4MjVjY2ZhM0oxCgdjcmV3X2lkEiYKJGU4ZDRhMjRhLWUyNjctNDk1ZC1hMDMz
|
||||
LTBiMjg4MGI0NDY3NkoeCgxjcmV3X3Byb2Nlc3MSDgoMaGllcmFyY2hpY2FsShEKC2NyZXdfbWVt
|
||||
b3J5EgIQAEoaChRjcmV3X251bWJlcl9vZl90YXNrcxICGAFKGwoVY3Jld19udW1iZXJfb2ZfYWdl
|
||||
bnRzEgIYAUrNAgoLY3Jld19hZ2VudHMSvQIKugJbeyJrZXkiOiAiOTJlN2ViMTkxNjY0YzkzNTc4
|
||||
NWVkN2Q0MjQwYTI5NGQiLCAiaWQiOiAiNWI5MjgxMmItNDY2Ny00NWY0LTk1YzItMTk1Mjg2Nzlh
|
||||
M2IyIiwgInJvbGUiOiAiU2NvcmVyIiwgInZlcmJvc2U/IjogZmFsc2UsICJtYXhfaXRlciI6IDIw
|
||||
LCAibWF4X3JwbSI6IG51bGwsICJmdW5jdGlvbl9jYWxsaW5nX2xsbSI6ICIiLCAibGxtIjogImdw
|
||||
dC00by1taW5pIiwgImRlbGVnYXRpb25fZW5hYmxlZD8iOiBmYWxzZSwgImFsbG93X2NvZGVfZXhl
|
||||
Y3V0aW9uPyI6IGZhbHNlLCAibWF4X3JldHJ5X2xpbWl0IjogMiwgInRvb2xzX25hbWVzIjogW119
|
||||
XUrbAQoKY3Jld190YXNrcxLMAQrJAVt7ImtleSI6ICIyN2VmMzhjYzk5ZGE0YThkZWQ3MGVkNDA2
|
||||
ZTQ0YWI4NiIsICJpZCI6ICJiNWE2ZWE1OS1mMGI5LTQ4MGItYTI5NS02MWJmMDI0N2ZiMTIiLCAi
|
||||
YXN5bmNfZXhlY3V0aW9uPyI6IGZhbHNlLCAiaHVtYW5faW5wdXQ/IjogZmFsc2UsICJhZ2VudF9y
|
||||
b2xlIjogIk5vbmUiLCAiYWdlbnRfa2V5IjogbnVsbCwgInRvb2xzX25hbWVzIjogW119XXoCGAGF
|
||||
AQABAAASjgIKEKaP9PExHsYn1Xk1pOUjbMASCNqZ3fr7T3qRKgxUYXNrIENyZWF0ZWQwATlv8+jW
|
||||
sqIiGEH37OnWsqIiGEouCghjcmV3X2tleRIiCiA1ZTZlZmZlNjgwYTVkOTdkYzM4NzNiMTQ4MjVj
|
||||
Y2ZhM0oxCgdjcmV3X2lkEiYKJGU4ZDRhMjRhLWUyNjctNDk1ZC1hMDMzLTBiMjg4MGI0NDY3Nkou
|
||||
Cgh0YXNrX2tleRIiCiAyN2VmMzhjYzk5ZGE0YThkZWQ3MGVkNDA2ZTQ0YWI4NkoxCgd0YXNrX2lk
|
||||
EiYKJGI1YTZlYTU5LWYwYjktNDgwYi1hMjk1LTYxYmYwMjQ3ZmIxMnoCGAGFAQABAAASmwEKEJIg
|
||||
3HTpmY/fSKiQgoPnmQkSCMJFtRfphlDlKgpUb29sIFVzYWdlMAE5AWr817KiIhhBQc4I2LKiIhhK
|
||||
GgoOY3Jld2FpX3ZlcnNpb24SCAoGMC44Ni4wSicKCXRvb2xfbmFtZRIaChhBc2sgcXVlc3Rpb24g
|
||||
dG8gY293b3JrZXJKDgoIYXR0ZW1wdHMSAhgBegIYAYUBAAEAABLVCQoQzrTMiYiXPQhcRxHVST04
|
||||
2BIIi9k1rxjdYnwqDENyZXcgQ3JlYXRlZDABOdj1LNmyoiIYQf94PdmyoiIYShoKDmNyZXdhaV92
|
||||
ZXJzaW9uEggKBjAuODYuMEoaCg5weXRob25fdmVyc2lvbhIICgYzLjEyLjdKLgoIY3Jld19rZXkS
|
||||
IgogNzQyNzU3MzEyZWY3YmI0ZWUwYjA2NjJkMWMyZTIxNzlKMQoHY3Jld19pZBImCiQ2MDQzOTVm
|
||||
ZC0xZTNjLTRiZDctYWUwYS0yMmQxZGYxOGI1ZWFKHAoMY3Jld19wcm9jZXNzEgwKCnNlcXVlbnRp
|
||||
YWxKEQoLY3Jld19tZW1vcnkSAhAAShoKFGNyZXdfbnVtYmVyX29mX3Rhc2tzEgIYAUobChVjcmV3
|
||||
X251bWJlcl9vZl9hZ2VudHMSAhgCSoYFCgtjcmV3X2FnZW50cxL2BArzBFt7ImtleSI6ICI4OWNm
|
||||
MzExYjQ4YjUyMTY5ZDQyZjM5MjVjNWJlMWM1YSIsICJpZCI6ICIyNWUzZWJiZC0zMTNhLTQxOTYt
|
||||
OTU5Yi1kMjkwOGM4YjFlYmUiLCAicm9sZSI6ICJNYW5hZ2VyIiwgInZlcmJvc2U/IjogZmFsc2Us
|
||||
ICJtYXhfaXRlciI6IDIwLCAibWF4X3JwbSI6IG51bGwsICJmdW5jdGlvbl9jYWxsaW5nX2xsbSI6
|
||||
ICIiLCAibGxtIjogImdwdC00by1taW5pIiwgImRlbGVnYXRpb25fZW5hYmxlZD8iOiB0cnVlLCAi
|
||||
YWxsb3dfY29kZV9leGVjdXRpb24/IjogZmFsc2UsICJtYXhfcmV0cnlfbGltaXQiOiAyLCAidG9v
|
||||
bHNfbmFtZXMiOiBbXX0sIHsia2V5IjogIjkyZTdlYjE5MTY2NGM5MzU3ODVlZDdkNDI0MGEyOTRk
|
||||
IiwgImlkIjogImEzNDExNGRlLTczOTYtNDRmYS1iMDQ1LWNhNDkwODkxYjk1OCIsICJyb2xlIjog
|
||||
IlNjb3JlciIsICJ2ZXJib3NlPyI6IGZhbHNlLCAibWF4X2l0ZXIiOiAyMCwgIm1heF9ycG0iOiBu
|
||||
dWxsLCAiZnVuY3Rpb25fY2FsbGluZ19sbG0iOiAiIiwgImxsbSI6ICJncHQtNG8tbWluaSIsICJk
|
||||
ZWxlZ2F0aW9uX2VuYWJsZWQ/IjogdHJ1ZSwgImFsbG93X2NvZGVfZXhlY3V0aW9uPyI6IGZhbHNl
|
||||
LCAibWF4X3JldHJ5X2xpbWl0IjogMiwgInRvb2xzX25hbWVzIjogW119XUr8AQoKY3Jld190YXNr
|
||||
cxLtAQrqAVt7ImtleSI6ICIyN2VmMzhjYzk5ZGE0YThkZWQ3MGVkNDA2ZTQ0YWI4NiIsICJpZCI6
|
||||
ICI5YjZjZWFhNy1kM2NiLTQ0OWYtYjQ2ZS1mZmEwNjlhYzgwMDEiLCAiYXN5bmNfZXhlY3V0aW9u
|
||||
PyI6IGZhbHNlLCAiaHVtYW5faW5wdXQ/IjogZmFsc2UsICJhZ2VudF9yb2xlIjogIk1hbmFnZXIi
|
||||
LCAiYWdlbnRfa2V5IjogIjg5Y2YzMTFiNDhiNTIxNjlkNDJmMzkyNWM1YmUxYzVhIiwgInRvb2xz
|
||||
X25hbWVzIjogW119XXoCGAGFAQABAAASjgIKEKJ4J7Oy475NBhJRuBFZ+cISCLYE49VIHKRJKgxU
|
||||
YXNrIENyZWF0ZWQwATkIiGvZsqIiGEH9QW3ZsqIiGEouCghjcmV3X2tleRIiCiA3NDI3NTczMTJl
|
||||
ZjdiYjRlZTBiMDY2MmQxYzJlMjE3OUoxCgdjcmV3X2lkEiYKJDYwNDM5NWZkLTFlM2MtNGJkNy1h
|
||||
ZTBhLTIyZDFkZjE4YjVlYUouCgh0YXNrX2tleRIiCiAyN2VmMzhjYzk5ZGE0YThkZWQ3MGVkNDA2
|
||||
ZTQ0YWI4NkoxCgd0YXNrX2lkEiYKJDliNmNlYWE3LWQzY2ItNDQ5Zi1iNDZlLWZmYTA2OWFjODAw
|
||||
MXoCGAGFAQABAAASnAEKEJKth6dXWvKIowQFEh7iL+QSCGC2zIPkyZo9KgpUb29sIFVzYWdlMAE5
|
||||
gH582rKiIhhBjVWI2rKiIhhKGgoOY3Jld2FpX3ZlcnNpb24SCAoGMC44Ni4wSigKCXRvb2xfbmFt
|
||||
ZRIbChlEZWxlZ2F0ZSB3b3JrIHRvIGNvd29ya2VySg4KCGF0dGVtcHRzEgIYAXoCGAGFAQABAAAS
|
||||
jwcKEC9Yct0YWoOggcmlLMY1qXwSCAwLqRG7HRH8KgxDcmV3IENyZWF0ZWQwATmH6rzbsqIiGEGr
|
||||
/sjbsqIiGEoaCg5jcmV3YWlfdmVyc2lvbhIICgYwLjg2LjBKGgoOcHl0aG9uX3ZlcnNpb24SCAoG
|
||||
My4xMi43Si4KCGNyZXdfa2V5EiIKIDMwM2I4ZWRkNWIwMDg3MTBkNzZhYWY4MjVhNzA5ZTU1SjEK
|
||||
B2NyZXdfaWQSJgokNmM0ZGU2MmYtNzI1NS00MTJhLTg5ODQtZGQ2YWY2ZTExNDE1Sh4KDGNyZXdf
|
||||
cHJvY2VzcxIOCgxoaWVyYXJjaGljYWxKEQoLY3Jld19tZW1vcnkSAhAAShoKFGNyZXdfbnVtYmVy
|
||||
X29mX3Rhc2tzEgIYAUobChVjcmV3X251bWJlcl9vZl9hZ2VudHMSAhgBSt8CCgtjcmV3X2FnZW50
|
||||
cxLPAgrMAlt7ImtleSI6ICI5MmU3ZWIxOTE2NjRjOTM1Nzg1ZWQ3ZDQyNDBhMjk0ZCIsICJpZCI6
|
||||
ICI1MGZiZDJiNy05ODM0LTRiZmQtYTIwMC02ZGNkZTYxMWE0Y2EiLCAicm9sZSI6ICJTY29yZXIi
|
||||
LCAidmVyYm9zZT8iOiBmYWxzZSwgIm1heF9pdGVyIjogMjAsICJtYXhfcnBtIjogbnVsbCwgImZ1
|
||||
bmN0aW9uX2NhbGxpbmdfbGxtIjogIiIsICJsbG0iOiAiZ3B0LTRvLW1pbmkiLCAiZGVsZWdhdGlv
|
||||
bl9lbmFibGVkPyI6IGZhbHNlLCAiYWxsb3dfY29kZV9leGVjdXRpb24/IjogZmFsc2UsICJtYXhf
|
||||
cmV0cnlfbGltaXQiOiAyLCAidG9vbHNfbmFtZXMiOiBbInNjb3JpbmdfZXhhbXBsZXMiXX1dStsB
|
||||
CgpjcmV3X3Rhc2tzEswBCskBW3sia2V5IjogImYzNTc1YjAxM2MyMjk0YjdjYzhlODAzMTU1Yzhi
|
||||
YTQ2IiwgImlkIjogIjIwMjAxZWUyLTI2MjItNDk5ZS04OGZkLWExMDBkMGQxMWUwOCIsICJhc3lu
|
||||
Y19leGVjdXRpb24/IjogZmFsc2UsICJodW1hbl9pbnB1dD8iOiBmYWxzZSwgImFnZW50X3JvbGUi
|
||||
OiAiTm9uZSIsICJhZ2VudF9rZXkiOiBudWxsLCAidG9vbHNfbmFtZXMiOiBbXX1degIYAYUBAAEA
|
||||
ABKOAgoQ3H05pcuuqd75dqsWGflj+RIIaBOcaXQKv6gqDFRhc2sgQ3JlYXRlZDABOVoaCtyyoiIY
|
||||
QSHdCtyyoiIYSi4KCGNyZXdfa2V5EiIKIDMwM2I4ZWRkNWIwMDg3MTBkNzZhYWY4MjVhNzA5ZTU1
|
||||
SjEKB2NyZXdfaWQSJgokNmM0ZGU2MmYtNzI1NS00MTJhLTg5ODQtZGQ2YWY2ZTExNDE1Si4KCHRh
|
||||
c2tfa2V5EiIKIGYzNTc1YjAxM2MyMjk0YjdjYzhlODAzMTU1YzhiYTQ2SjEKB3Rhc2tfaWQSJgok
|
||||
MjAyMDFlZTItMjYyMi00OTllLTg4ZmQtYTEwMGQwZDExZTA4egIYAYUBAAEAABJoChDY5L3dzdeM
|
||||
3SiXFLdirF97EgjBlCb4I8cu4CoQVG9vbCBVc2FnZSBFcnJvcjABOQZ5J92yoiIYQeT7Mt2yoiIY
|
||||
ShoKDmNyZXdhaV92ZXJzaW9uEggKBjAuODYuMHoCGAGFAQABAAASnAEKECYW4KrnGSVLVOZuOqEr
|
||||
4dQSCPfhCGICL36EKgpUb29sIFVzYWdlMAE5+BrR3rKiIhhB8Eve3rKiIhhKGgoOY3Jld2FpX3Zl
|
||||
cnNpb24SCAoGMC44Ni4wSigKCXRvb2xfbmFtZRIbChlEZWxlZ2F0ZSB3b3JrIHRvIGNvd29ya2Vy
|
||||
Sg4KCGF0dGVtcHRzEgIYAXoCGAGFAQABAAA=
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Length:
|
||||
- '30065'
|
||||
Content-Type:
|
||||
- application/x-protobuf
|
||||
User-Agent:
|
||||
- OTel-OTLP-Exporter-Python/1.27.0
|
||||
method: POST
|
||||
uri: https://telemetry.crewai.com:4319/v1/traces
|
||||
response:
|
||||
body:
|
||||
string: "\n\0"
|
||||
headers:
|
||||
Content-Length:
|
||||
- '2'
|
||||
Content-Type:
|
||||
- application/x-protobuf
|
||||
Date:
|
||||
- Sun, 09 Feb 2025 20:01:37 GMT
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
- request:
|
||||
body: '{"messages": [{"role": "system", "content": "You are Communications Manager.
|
||||
You''re a communications expert\nYour personal goal is: Manage communications\nTo
|
||||
give my best complete final answer to the task use the exact following format:\n\nThought:
|
||||
I now can give a great answer\nFinal Answer: Your final answer must be the great
|
||||
and the most complete as possible, it must be outcome described.\n\nI MUST use
|
||||
these formats, my job depends on it!"}, {"role": "user", "content": "\nCurrent
|
||||
Task: Handle PR\n\nThis is the expect criteria for your final answer: Your best
|
||||
answer to your coworker asking you this, accounting for the context shared.\nyou
|
||||
MUST return the actual complete content as the final answer, not a summary.\n\nThis
|
||||
is the context you''re working with:\nImportant announcement\n\nBegin! This
|
||||
is VERY important to you, use the tools available and give your best Final Answer,
|
||||
your job depends on it!\n\nThought:"}], "model": "gpt-4o-mini", "stop": ["\nObservation:"],
|
||||
"stream": false}'
|
||||
headers:
|
||||
accept:
|
||||
- application/json
|
||||
accept-encoding:
|
||||
- gzip, deflate
|
||||
connection:
|
||||
- keep-alive
|
||||
content-length:
|
||||
- '999'
|
||||
content-type:
|
||||
- application/json
|
||||
cookie:
|
||||
- _cfuvid=FasG_74jjKfEtA2Mjn2iKdu62tv3zosBxYNYTk1E12M-1734025911900-0.0.1.1-604800000
|
||||
host:
|
||||
- api.openai.com
|
||||
user-agent:
|
||||
- OpenAI/Python 1.52.1
|
||||
x-stainless-arch:
|
||||
- x64
|
||||
x-stainless-async:
|
||||
- 'false'
|
||||
x-stainless-lang:
|
||||
- python
|
||||
x-stainless-os:
|
||||
- Linux
|
||||
x-stainless-package-version:
|
||||
- 1.52.1
|
||||
x-stainless-raw-response:
|
||||
- 'true'
|
||||
x-stainless-retry-count:
|
||||
- '0'
|
||||
x-stainless-runtime:
|
||||
- CPython
|
||||
x-stainless-runtime-version:
|
||||
- 3.12.7
|
||||
method: POST
|
||||
uri: https://api.openai.com/v1/chat/completions
|
||||
response:
|
||||
content: "{\n \"id\": \"chatcmpl-Az7mh3n54jjRqOmwiIwwfdm7aSpeH\",\n \"object\":
|
||||
\"chat.completion\",\n \"created\": 1739131295,\n \"model\": \"gpt-4o-mini-2024-07-18\",\n
|
||||
\ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\":
|
||||
\"assistant\",\n \"content\": \"I now can give a great answer \\nFinal
|
||||
Answer: \\n\\nDear Team,\\n\\nI am writing to share an important announcement
|
||||
that requires our immediate attention and thoughtful consideration. As we continue
|
||||
to uphold our commitment to transparency and engagement with our stakeholders,
|
||||
it is critical that we effectively manage our public relations (PR) in light
|
||||
of this recent development.\\n\\nThe primary goal of our communications strategy
|
||||
moving forward should be to clearly articulate the message surrounding this
|
||||
announcement. We want to ensure that our audience understands the relevance
|
||||
of this news and how it impacts our organization, our clients, and our broader
|
||||
community.\\n\\nHere are the steps we will take to handle this situation effectively:\\n\\n1.
|
||||
**Crafting the Message**: We need to draft a clear and concise press release
|
||||
that outlines the key details of the announcement. This should include the \\\"who,
|
||||
what, when, where, and why\\\" in a manner that is easily understandable.\\n\\n2.
|
||||
**Targeting Our Audience**: Identify the key stakeholders, including media outlets,
|
||||
industry influencers, and our internal team. Tailoring our message for each
|
||||
segment will maximize our reach and ensure that the right people receive the
|
||||
information.\\n\\n3. **Media Outreach**: We will follow up the press release
|
||||
with personal outreach to select reporters and journalists who cover topics
|
||||
relevant to our announcement. Building these relationships can enhance the likelihood
|
||||
of positive coverage.\\n\\n4. **Social Media Strategy**: Leverage our social
|
||||
media platforms to create buzz around the announcement. Use engaging visuals
|
||||
and narratives that encourage shares and dialogue. This will help increase visibility
|
||||
and drive traffic to our official channels.\\n\\n5. **Internal Communication**:
|
||||
Ensure that our employees are informed about the announcement before it goes
|
||||
public. We will hold an all-hands meeting or send a detailed email, allowing
|
||||
them to ask questions and express concerns, fostering an inclusive environment.\\n\\n6.
|
||||
**Monitoring and Response**: After the announcement, we will actively monitor
|
||||
media coverage and social media mentions. We should be prepared to respond to
|
||||
any inquiries or comments from the media or the public promptly and thoughtfully.\\n\\n7.
|
||||
**Review and Adjust**: After our communications efforts are underway, we will
|
||||
review the outcomes and make adjustments as needed. Gathering feedback from
|
||||
our stakeholders will help guide our future PR strategies.\\n\\nOur goal is
|
||||
to present this announcement in a way that reflects positively on our organization
|
||||
and resonates with our audience. Let's work together to ensure its success.\\n\\nThank
|
||||
you for prioritizing this matter and for your commitment to excellent communication.\\n\\nBest,
|
||||
\ \\n[Your Name] \\nCommunications Manager\",\n \"refusal\": null\n
|
||||
\ },\n \"logprobs\": null,\n \"finish_reason\": \"stop\"\n }\n
|
||||
\ ],\n \"usage\": {\n \"prompt_tokens\": 179,\n \"completion_tokens\":
|
||||
501,\n \"total_tokens\": 680,\n \"prompt_tokens_details\": {\n \"cached_tokens\":
|
||||
0,\n \"audio_tokens\": 0\n },\n \"completion_tokens_details\": {\n
|
||||
\ \"reasoning_tokens\": 0,\n \"audio_tokens\": 0,\n \"accepted_prediction_tokens\":
|
||||
0,\n \"rejected_prediction_tokens\": 0\n }\n },\n \"service_tier\":
|
||||
\"default\",\n \"system_fingerprint\": \"fp_72ed7ab54c\"\n}\n"
|
||||
headers:
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-RAY:
|
||||
- 90f673c60f8f7630-SEA
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Encoding:
|
||||
- gzip
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Sun, 09 Feb 2025 20:01:42 GMT
|
||||
Server:
|
||||
- cloudflare
|
||||
Set-Cookie:
|
||||
- __cf_bm=H1ZUJLFQyjA_Hrd4Z76CRvULzgvM.SGqv5BxlqcLtsk-1739131302-1.0.1.1-pCaz3BNn_biaNVKIBmZ4O4ERAWiRQI1jXb.z5kZ4DwTSSKRRIBPUyFSpS1zNZ88BfpLPbg0DvaS0bzkg0Cwieg;
|
||||
path=/; expires=Sun, 09-Feb-25 20:31:42 GMT; domain=.api.openai.com; HttpOnly;
|
||||
Secure; SameSite=None
|
||||
- _cfuvid=Y2wLyNWVVzDV7PV3OQmGIaKSa_xooNjD09ArUEtmrSw-1739131302950-0.0.1.1-604800000;
|
||||
path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
access-control-expose-headers:
|
||||
- X-Request-ID
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
openai-organization:
|
||||
- crewai-iuxna1
|
||||
openai-processing-ms:
|
||||
- '7153'
|
||||
openai-version:
|
||||
- '2020-10-01'
|
||||
strict-transport-security:
|
||||
- max-age=31536000; includeSubDomains; preload
|
||||
x-ratelimit-limit-requests:
|
||||
- '30000'
|
||||
x-ratelimit-limit-tokens:
|
||||
- '150000000'
|
||||
x-ratelimit-remaining-requests:
|
||||
- '29999'
|
||||
x-ratelimit-remaining-tokens:
|
||||
- '149999774'
|
||||
x-ratelimit-reset-requests:
|
||||
- 2ms
|
||||
x-ratelimit-reset-tokens:
|
||||
- 0s
|
||||
x-request-id:
|
||||
- req_79183b42e5901f1a93eb756898cb0795
|
||||
http_version: HTTP/1.1
|
||||
status_code: 200
|
||||
version: 1
|
||||
@@ -1,134 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: '{"messages": [{"role": "system", "content": "You are Research Manager.
|
||||
You''re a research expert\nYour personal goal is: Manage research\nTo give my
|
||||
best complete final answer to the task use the exact following format:\n\nThought:
|
||||
I now can give a great answer\nFinal Answer: Your final answer must be the great
|
||||
and the most complete as possible, it must be outcome described.\n\nI MUST use
|
||||
these formats, my job depends on it!"}, {"role": "user", "content": "\nCurrent
|
||||
Task: Handle research\n\nThis is the expect criteria for your final answer:
|
||||
Your best answer to your coworker asking you this, accounting for the context
|
||||
shared.\nyou MUST return the actual complete content as the final answer, not
|
||||
a summary.\n\nThis is the context you''re working with:\nImportant research\n\nBegin!
|
||||
This is VERY important to you, use the tools available and give your best Final
|
||||
Answer, your job depends on it!\n\nThought:"}], "model": "gpt-4o-mini", "stop":
|
||||
["\nObservation:"], "stream": false}'
|
||||
headers:
|
||||
accept:
|
||||
- application/json
|
||||
accept-encoding:
|
||||
- gzip, deflate
|
||||
connection:
|
||||
- keep-alive
|
||||
content-length:
|
||||
- '983'
|
||||
content-type:
|
||||
- application/json
|
||||
cookie:
|
||||
- _cfuvid=GxztReZeGi6qENS0TkwOuBgjGx3aFWu5H5e9HnTkQRI-1739131802782-0.0.1.1-604800000;
|
||||
__cf_bm=UYR3lic9ZX3q_w8ul5YU1NoMKLvuFEK8LNu_O.5QPcU-1739131802-1.0.1.1-K5kQYiuLVp2wZpT4pe1oC.zjo4mBzVzXvfIChY.A419uN54s97KQRauV2PBI5ArtsbDEMIaVV3GOZaAtCfAClg
|
||||
host:
|
||||
- api.openai.com
|
||||
user-agent:
|
||||
- OpenAI/Python 1.52.1
|
||||
x-stainless-arch:
|
||||
- x64
|
||||
x-stainless-async:
|
||||
- 'false'
|
||||
x-stainless-lang:
|
||||
- python
|
||||
x-stainless-os:
|
||||
- Linux
|
||||
x-stainless-package-version:
|
||||
- 1.52.1
|
||||
x-stainless-raw-response:
|
||||
- 'true'
|
||||
x-stainless-retry-count:
|
||||
- '0'
|
||||
x-stainless-runtime:
|
||||
- CPython
|
||||
x-stainless-runtime-version:
|
||||
- 3.12.7
|
||||
method: POST
|
||||
uri: https://api.openai.com/v1/chat/completions
|
||||
response:
|
||||
content: "{\n \"id\": \"chatcmpl-Az7usRsnv7YVDLrlprCZSD9s2EZw0\",\n \"object\":
|
||||
\"chat.completion\",\n \"created\": 1739131802,\n \"model\": \"gpt-4o-mini-2024-07-18\",\n
|
||||
\ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\":
|
||||
\"assistant\",\n \"content\": \"I now can give a great answer \\nFinal
|
||||
Answer: To effectively handle this important research, we must first establish
|
||||
a clear framework that outlines our objectives, methodologies, and expected
|
||||
outcomes. This includes defining the key research questions we aim to answer,
|
||||
identifying the target population for our study, and selecting appropriate research
|
||||
methods\u2014whether qualitative, quantitative, or a mixed approach.\\n\\nNext,
|
||||
we should gather and analyze existing literature related to our research topic
|
||||
to ensure we build upon existing knowledge and identify gaps that our study
|
||||
could address. It\u2019s essential to collect data systematically, while considering
|
||||
ethical guidelines, to ensure integrity and reliability in our findings.\\n\\nOnce
|
||||
data collection is complete, we will utilize statistical software or qualitative
|
||||
analysis tools to interpret our results accurately. Our end goal is to derive
|
||||
meaningful conclusions that can inform stakeholders and promote actionable insights.
|
||||
\\n\\nTo ensure our research resonates and is disseminated effectively, we will
|
||||
prepare a comprehensive report, highlighting our methodology, findings, and
|
||||
implications. This report should be designed for various audiences, making it
|
||||
both accessible to the wider public and detailed enough for academic scrutiny.\\n\\nIn
|
||||
conclusion, our research will not only contribute to the body of knowledge in
|
||||
our field but also provide pivotal insights that can guide policy and future
|
||||
studies. Collaboration and consistent communication throughout this process
|
||||
will be key to our success. Thus, let us prioritize this research as an integral
|
||||
part of our goals moving forward.\",\n \"refusal\": null\n },\n
|
||||
\ \"logprobs\": null,\n \"finish_reason\": \"stop\"\n }\n ],\n
|
||||
\ \"usage\": {\n \"prompt_tokens\": 179,\n \"completion_tokens\": 275,\n
|
||||
\ \"total_tokens\": 454,\n \"prompt_tokens_details\": {\n \"cached_tokens\":
|
||||
0,\n \"audio_tokens\": 0\n },\n \"completion_tokens_details\": {\n
|
||||
\ \"reasoning_tokens\": 0,\n \"audio_tokens\": 0,\n \"accepted_prediction_tokens\":
|
||||
0,\n \"rejected_prediction_tokens\": 0\n }\n },\n \"service_tier\":
|
||||
\"default\",\n \"system_fingerprint\": \"fp_72ed7ab54c\"\n}\n"
|
||||
headers:
|
||||
CF-RAY:
|
||||
- 90f68027cd8a76f1-SEA
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Encoding:
|
||||
- gzip
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Sun, 09 Feb 2025 20:10:06 GMT
|
||||
Server:
|
||||
- cloudflare
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
access-control-expose-headers:
|
||||
- X-Request-ID
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
cf-cache-status:
|
||||
- DYNAMIC
|
||||
openai-organization:
|
||||
- crewai-iuxna1
|
||||
openai-processing-ms:
|
||||
- '3496'
|
||||
openai-version:
|
||||
- '2020-10-01'
|
||||
strict-transport-security:
|
||||
- max-age=31536000; includeSubDomains; preload
|
||||
x-ratelimit-limit-requests:
|
||||
- '30000'
|
||||
x-ratelimit-limit-tokens:
|
||||
- '150000000'
|
||||
x-ratelimit-remaining-requests:
|
||||
- '29999'
|
||||
x-ratelimit-remaining-tokens:
|
||||
- '149999777'
|
||||
x-ratelimit-reset-requests:
|
||||
- 2ms
|
||||
x-ratelimit-reset-tokens:
|
||||
- 0s
|
||||
x-request-id:
|
||||
- req_17b6c277c477e2f7bd3bbff2429c1132
|
||||
http_version: HTTP/1.1
|
||||
status_code: 200
|
||||
version: 1
|
||||
@@ -1,674 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: !!binary |
|
||||
Cq7aAQokCiIKDHNlcnZpY2UubmFtZRISChBjcmV3QUktdGVsZW1ldHJ5EoTaAQoSChBjcmV3YWku
|
||||
dGVsZW1ldHJ5EpoMChCQ5FhZBLWobT0rBv/c/LVHEgguk747KR8dSioMQ3JldyBDcmVhdGVkMAE5
|
||||
kf+biSSjIhhBYc+viSSjIhhKGgoOY3Jld2FpX3ZlcnNpb24SCAoGMC44Ni4wShoKDnB5dGhvbl92
|
||||
ZXJzaW9uEggKBjMuMTIuN0ouCghjcmV3X2tleRIiCiAxZjEyOGJkYjdiYWE0YjY3NzE0ZjFkYWVk
|
||||
YzJmM2FiNkoxCgdjcmV3X2lkEiYKJDc1YTdhN2U4LTFjMWQtNDRmOS1hMjYzLTU2MDBkZGMwMzQ3
|
||||
NEocCgxjcmV3X3Byb2Nlc3MSDAoKc2VxdWVudGlhbEoRCgtjcmV3X21lbW9yeRICEABKGgoUY3Jl
|
||||
d19udW1iZXJfb2ZfdGFza3MSAhgCShsKFWNyZXdfbnVtYmVyX29mX2FnZW50cxICGAJKtAUKC2Ny
|
||||
ZXdfYWdlbnRzEqQFCqEFW3sia2V5IjogIjczYzM0OWM5M2MxNjNiNWQ0ZGY5OGE2NGZhYzFjNDMw
|
||||
IiwgImlkIjogImYyNmRmMDA4LWJkYWMtNDA4YS1hMmE2LTcwNjAwZDM4N2I3ZCIsICJyb2xlIjog
|
||||
Int0b3BpY30gU2VuaW9yIERhdGEgUmVzZWFyY2hlclxuIiwgInZlcmJvc2U/IjogdHJ1ZSwgIm1h
|
||||
eF9pdGVyIjogMjAsICJtYXhfcnBtIjogbnVsbCwgImZ1bmN0aW9uX2NhbGxpbmdfbGxtIjogIiIs
|
||||
ICJsbG0iOiAiZ3B0LTRvLW1pbmkiLCAiZGVsZWdhdGlvbl9lbmFibGVkPyI6IGZhbHNlLCAiYWxs
|
||||
b3dfY29kZV9leGVjdXRpb24/IjogZmFsc2UsICJtYXhfcmV0cnlfbGltaXQiOiAyLCAidG9vbHNf
|
||||
bmFtZXMiOiBbXX0sIHsia2V5IjogIjEwNGZlMDY1OWUxMGI0MjZjZjg4ZjAyNGZiNTcxNTUzIiwg
|
||||
ImlkIjogIjJlMTZjZTFhLWFmMWYtNGRlNS1iOTFlLWQ2NjFiN2UwYzk1MyIsICJyb2xlIjogInt0
|
||||
b3BpY30gUmVwb3J0aW5nIEFuYWx5c3RcbiIsICJ2ZXJib3NlPyI6IHRydWUsICJtYXhfaXRlciI6
|
||||
IDIwLCAibWF4X3JwbSI6IG51bGwsICJmdW5jdGlvbl9jYWxsaW5nX2xsbSI6ICIiLCAibGxtIjog
|
||||
ImdwdC00by1taW5pIiwgImRlbGVnYXRpb25fZW5hYmxlZD8iOiBmYWxzZSwgImFsbG93X2NvZGVf
|
||||
ZXhlY3V0aW9uPyI6IGZhbHNlLCAibWF4X3JldHJ5X2xpbWl0IjogMiwgInRvb2xzX25hbWVzIjog
|
||||
W119XUqTBAoKY3Jld190YXNrcxKEBAqBBFt7ImtleSI6ICI2YWZjNGIzOTYyNTlmYmI3NjgxZjU2
|
||||
Yzc3NTVjYzkzNyIsICJpZCI6ICJjYWYwMTZkMC0zYzEyLTRiNDktYWRjNy0xOTdhMGZlZjk5MGIi
|
||||
LCAiYXN5bmNfZXhlY3V0aW9uPyI6IGZhbHNlLCAiaHVtYW5faW5wdXQ/IjogZmFsc2UsICJhZ2Vu
|
||||
dF9yb2xlIjogInt0b3BpY30gU2VuaW9yIERhdGEgUmVzZWFyY2hlclxuIiwgImFnZW50X2tleSI6
|
||||
ICI3M2MzNDljOTNjMTYzYjVkNGRmOThhNjRmYWMxYzQzMCIsICJ0b29sc19uYW1lcyI6IFtdfSwg
|
||||
eyJrZXkiOiAiYjE3YjE4OGRiZjE0ZjkzYTk4ZTViOTVhYWQzNjc1NzciLCAiaWQiOiAiYmU5NTY2
|
||||
NWEtNmExNi00ZTM0LTkwZmMtN2MwZjkyYzViZTZhIiwgImFzeW5jX2V4ZWN1dGlvbj8iOiBmYWxz
|
||||
ZSwgImh1bWFuX2lucHV0PyI6IGZhbHNlLCAiYWdlbnRfcm9sZSI6ICJ7dG9waWN9IFJlcG9ydGlu
|
||||
ZyBBbmFseXN0XG4iLCAiYWdlbnRfa2V5IjogIjEwNGZlMDY1OWUxMGI0MjZjZjg4ZjAyNGZiNTcx
|
||||
NTUzIiwgInRvb2xzX25hbWVzIjogW119XXoCGAGFAQABAAASjgIKEAE0SzVsw8CdYtGYIGpLKiUS
|
||||
CNlgq2BWlIvGKgxUYXNrIENyZWF0ZWQwATlB7t6JJKMiGEEv9t+JJKMiGEouCghjcmV3X2tleRIi
|
||||
CiAxZjEyOGJkYjdiYWE0YjY3NzE0ZjFkYWVkYzJmM2FiNkoxCgdjcmV3X2lkEiYKJDc1YTdhN2U4
|
||||
LTFjMWQtNDRmOS1hMjYzLTU2MDBkZGMwMzQ3NEouCgh0YXNrX2tleRIiCiA2YWZjNGIzOTYyNTlm
|
||||
YmI3NjgxZjU2Yzc3NTVjYzkzN0oxCgd0YXNrX2lkEiYKJGNhZjAxNmQwLTNjMTItNGI0OS1hZGM3
|
||||
LTE5N2EwZmVmOTkwYnoCGAGFAQABAAASjgIKEJhOc9cjzreo7oCThQQ8ilASCGOERJKgE7YhKgxU
|
||||
YXNrIENyZWF0ZWQwATlPIDaOJKMiGEENYUCOJKMiGEouCghjcmV3X2tleRIiCiAxZjEyOGJkYjdi
|
||||
YWE0YjY3NzE0ZjFkYWVkYzJmM2FiNkoxCgdjcmV3X2lkEiYKJDc1YTdhN2U4LTFjMWQtNDRmOS1h
|
||||
MjYzLTU2MDBkZGMwMzQ3NEouCgh0YXNrX2tleRIiCiBiMTdiMTg4ZGJmMTRmOTNhOThlNWI5NWFh
|
||||
ZDM2NzU3N0oxCgd0YXNrX2lkEiYKJGJlOTU2NjVhLTZhMTYtNGUzNC05MGZjLTdjMGY5MmM1YmU2
|
||||
YXoCGAGFAQABAAASmgwKEEMJbdoxmTm2pHBD8VKi4joSCKGTPPRVqoGmKgxDcmV3IENyZWF0ZWQw
|
||||
ATmk0UmdJKMiGEEPDF6dJKMiGEoaCg5jcmV3YWlfdmVyc2lvbhIICgYwLjg2LjBKGgoOcHl0aG9u
|
||||
X3ZlcnNpb24SCAoGMy4xMi43Si4KCGNyZXdfa2V5EiIKIDFmMTI4YmRiN2JhYTRiNjc3MTRmMWRh
|
||||
ZWRjMmYzYWI2SjEKB2NyZXdfaWQSJgokZTAzMjk4Y2MtOTRiOS00ZjZhLWFiMWYtNmE2ODYxZGMy
|
||||
NDA3ShwKDGNyZXdfcHJvY2VzcxIMCgpzZXF1ZW50aWFsShEKC2NyZXdfbWVtb3J5EgIQAEoaChRj
|
||||
cmV3X251bWJlcl9vZl90YXNrcxICGAJKGwoVY3Jld19udW1iZXJfb2ZfYWdlbnRzEgIYAkq0BQoL
|
||||
Y3Jld19hZ2VudHMSpAUKoQVbeyJrZXkiOiAiNzNjMzQ5YzkzYzE2M2I1ZDRkZjk4YTY0ZmFjMWM0
|
||||
MzAiLCAiaWQiOiAiNzdlYWY2NTQtYmQyZC00YzJkLThkODYtZGMyMGExNmRiMjU4IiwgInJvbGUi
|
||||
OiAie3RvcGljfSBTZW5pb3IgRGF0YSBSZXNlYXJjaGVyXG4iLCAidmVyYm9zZT8iOiB0cnVlLCAi
|
||||
bWF4X2l0ZXIiOiAyMCwgIm1heF9ycG0iOiBudWxsLCAiZnVuY3Rpb25fY2FsbGluZ19sbG0iOiAi
|
||||
IiwgImxsbSI6ICJncHQtNG8tbWluaSIsICJkZWxlZ2F0aW9uX2VuYWJsZWQ/IjogZmFsc2UsICJh
|
||||
bGxvd19jb2RlX2V4ZWN1dGlvbj8iOiBmYWxzZSwgIm1heF9yZXRyeV9saW1pdCI6IDIsICJ0b29s
|
||||
c19uYW1lcyI6IFtdfSwgeyJrZXkiOiAiMTA0ZmUwNjU5ZTEwYjQyNmNmODhmMDI0ZmI1NzE1NTMi
|
||||
LCAiaWQiOiAiNTNjYWY2MmEtMmI2Yy00MTYyLTg1YTQtYmMzODM5MDBhNTk4IiwgInJvbGUiOiAi
|
||||
e3RvcGljfSBSZXBvcnRpbmcgQW5hbHlzdFxuIiwgInZlcmJvc2U/IjogdHJ1ZSwgIm1heF9pdGVy
|
||||
IjogMjAsICJtYXhfcnBtIjogbnVsbCwgImZ1bmN0aW9uX2NhbGxpbmdfbGxtIjogIiIsICJsbG0i
|
||||
OiAiZ3B0LTRvLW1pbmkiLCAiZGVsZWdhdGlvbl9lbmFibGVkPyI6IGZhbHNlLCAiYWxsb3dfY29k
|
||||
ZV9leGVjdXRpb24/IjogZmFsc2UsICJtYXhfcmV0cnlfbGltaXQiOiAyLCAidG9vbHNfbmFtZXMi
|
||||
OiBbXX1dSpMECgpjcmV3X3Rhc2tzEoQECoEEW3sia2V5IjogIjZhZmM0YjM5NjI1OWZiYjc2ODFm
|
||||
NTZjNzc1NWNjOTM3IiwgImlkIjogIjdiNGVhN2UzLTYwZmMtNDhlMi04OWQ4LWIzYTNlNjhlY2Jl
|
||||
NyIsICJhc3luY19leGVjdXRpb24/IjogZmFsc2UsICJodW1hbl9pbnB1dD8iOiBmYWxzZSwgImFn
|
||||
ZW50X3JvbGUiOiAie3RvcGljfSBTZW5pb3IgRGF0YSBSZXNlYXJjaGVyXG4iLCAiYWdlbnRfa2V5
|
||||
IjogIjczYzM0OWM5M2MxNjNiNWQ0ZGY5OGE2NGZhYzFjNDMwIiwgInRvb2xzX25hbWVzIjogW119
|
||||
LCB7ImtleSI6ICJiMTdiMTg4ZGJmMTRmOTNhOThlNWI5NWFhZDM2NzU3NyIsICJpZCI6ICIyOGYz
|
||||
YTZiYS1jNjgyLTRiMWMtODQxNi1lMzY2MGRlOGVkYzciLCAiYXN5bmNfZXhlY3V0aW9uPyI6IGZh
|
||||
bHNlLCAiaHVtYW5faW5wdXQ/IjogZmFsc2UsICJhZ2VudF9yb2xlIjogInt0b3BpY30gUmVwb3J0
|
||||
aW5nIEFuYWx5c3RcbiIsICJhZ2VudF9rZXkiOiAiMTA0ZmUwNjU5ZTEwYjQyNmNmODhmMDI0ZmI1
|
||||
NzE1NTMiLCAidG9vbHNfbmFtZXMiOiBbXX1degIYAYUBAAEAABKOAgoQA3fjsnaQujXeI3OARv8f
|
||||
nxII/MZ1gl15VYMqDFRhc2sgQ3JlYXRlZDABOYdGip0koyIYQaU+i50koyIYSi4KCGNyZXdfa2V5
|
||||
EiIKIDFmMTI4YmRiN2JhYTRiNjc3MTRmMWRhZWRjMmYzYWI2SjEKB2NyZXdfaWQSJgokZTAzMjk4
|
||||
Y2MtOTRiOS00ZjZhLWFiMWYtNmE2ODYxZGMyNDA3Si4KCHRhc2tfa2V5EiIKIDZhZmM0YjM5NjI1
|
||||
OWZiYjc2ODFmNTZjNzc1NWNjOTM3SjEKB3Rhc2tfaWQSJgokN2I0ZWE3ZTMtNjBmYy00OGUyLTg5
|
||||
ZDgtYjNhM2U2OGVjYmU3egIYAYUBAAEAABKOAgoQKPBsDS1rOhko6EetVAVvExIIZ6cTYyXqh/gq
|
||||
DFRhc2sgQ3JlYXRlZDABOfhSo6AkoyIYQbdOpaAkoyIYSi4KCGNyZXdfa2V5EiIKIDFmMTI4YmRi
|
||||
N2JhYTRiNjc3MTRmMWRhZWRjMmYzYWI2SjEKB2NyZXdfaWQSJgokZTAzMjk4Y2MtOTRiOS00ZjZh
|
||||
LWFiMWYtNmE2ODYxZGMyNDA3Si4KCHRhc2tfa2V5EiIKIGIxN2IxODhkYmYxNGY5M2E5OGU1Yjk1
|
||||
YWFkMzY3NTc3SjEKB3Rhc2tfaWQSJgokMjhmM2E2YmEtYzY4Mi00YjFjLTg0MTYtZTM2NjBkZThl
|
||||
ZGM3egIYAYUBAAEAABKaDAoQwHWhvBxsx99MB/BLWSeDDRIIKTnfz9P27hAqDENyZXcgQ3JlYXRl
|
||||
ZDABOffc07EkoyIYQX5a47EkoyIYShoKDmNyZXdhaV92ZXJzaW9uEggKBjAuODYuMEoaCg5weXRo
|
||||
b25fdmVyc2lvbhIICgYzLjEyLjdKLgoIY3Jld19rZXkSIgogMWYxMjhiZGI3YmFhNGI2NzcxNGYx
|
||||
ZGFlZGMyZjNhYjZKMQoHY3Jld19pZBImCiQ0NGUwY2U0ZC0xZDEyLTRhNWItODI5Mi0yOWQ2OTI5
|
||||
OTcyM2NKHAoMY3Jld19wcm9jZXNzEgwKCnNlcXVlbnRpYWxKEQoLY3Jld19tZW1vcnkSAhAAShoK
|
||||
FGNyZXdfbnVtYmVyX29mX3Rhc2tzEgIYAkobChVjcmV3X251bWJlcl9vZl9hZ2VudHMSAhgCSrQF
|
||||
CgtjcmV3X2FnZW50cxKkBQqhBVt7ImtleSI6ICI3M2MzNDljOTNjMTYzYjVkNGRmOThhNjRmYWMx
|
||||
YzQzMCIsICJpZCI6ICJlNmUzOWMwOC02ZWZlLTRjNDEtYjdhNi0xMmFlODBlNGI4ZjMiLCAicm9s
|
||||
ZSI6ICJ7dG9waWN9IFNlbmlvciBEYXRhIFJlc2VhcmNoZXJcbiIsICJ2ZXJib3NlPyI6IHRydWUs
|
||||
ICJtYXhfaXRlciI6IDIwLCAibWF4X3JwbSI6IG51bGwsICJmdW5jdGlvbl9jYWxsaW5nX2xsbSI6
|
||||
ICIiLCAibGxtIjogImdwdC00by1taW5pIiwgImRlbGVnYXRpb25fZW5hYmxlZD8iOiBmYWxzZSwg
|
||||
ImFsbG93X2NvZGVfZXhlY3V0aW9uPyI6IGZhbHNlLCAibWF4X3JldHJ5X2xpbWl0IjogMiwgInRv
|
||||
b2xzX25hbWVzIjogW119LCB7ImtleSI6ICIxMDRmZTA2NTllMTBiNDI2Y2Y4OGYwMjRmYjU3MTU1
|
||||
MyIsICJpZCI6ICJhYjhlZDYzNy0zZTFkLTQzOWYtYWUxZC1mZTI5MGQyNDkwODYiLCAicm9sZSI6
|
||||
ICJ7dG9waWN9IFJlcG9ydGluZyBBbmFseXN0XG4iLCAidmVyYm9zZT8iOiB0cnVlLCAibWF4X2l0
|
||||
ZXIiOiAyMCwgIm1heF9ycG0iOiBudWxsLCAiZnVuY3Rpb25fY2FsbGluZ19sbG0iOiAiIiwgImxs
|
||||
bSI6ICJncHQtNG8tbWluaSIsICJkZWxlZ2F0aW9uX2VuYWJsZWQ/IjogZmFsc2UsICJhbGxvd19j
|
||||
b2RlX2V4ZWN1dGlvbj8iOiBmYWxzZSwgIm1heF9yZXRyeV9saW1pdCI6IDIsICJ0b29sc19uYW1l
|
||||
cyI6IFtdfV1KkwQKCmNyZXdfdGFza3MShAQKgQRbeyJrZXkiOiAiNmFmYzRiMzk2MjU5ZmJiNzY4
|
||||
MWY1NmM3NzU1Y2M5MzciLCAiaWQiOiAiM2NjM2IyNWMtOGQ5Yi00YjBhLWEyZWUtNmNjNmI0YWY5
|
||||
MGU0IiwgImFzeW5jX2V4ZWN1dGlvbj8iOiBmYWxzZSwgImh1bWFuX2lucHV0PyI6IGZhbHNlLCAi
|
||||
YWdlbnRfcm9sZSI6ICJ7dG9waWN9IFNlbmlvciBEYXRhIFJlc2VhcmNoZXJcbiIsICJhZ2VudF9r
|
||||
ZXkiOiAiNzNjMzQ5YzkzYzE2M2I1ZDRkZjk4YTY0ZmFjMWM0MzAiLCAidG9vbHNfbmFtZXMiOiBb
|
||||
XX0sIHsia2V5IjogImIxN2IxODhkYmYxNGY5M2E5OGU1Yjk1YWFkMzY3NTc3IiwgImlkIjogIjkw
|
||||
ZTE4MjJlLTQwZTktNDViYi04MGQ2LTQ0NzI0N2U4Yzk5ZCIsICJhc3luY19leGVjdXRpb24/Ijog
|
||||
ZmFsc2UsICJodW1hbl9pbnB1dD8iOiBmYWxzZSwgImFnZW50X3JvbGUiOiAie3RvcGljfSBSZXBv
|
||||
cnRpbmcgQW5hbHlzdFxuIiwgImFnZW50X2tleSI6ICIxMDRmZTA2NTllMTBiNDI2Y2Y4OGYwMjRm
|
||||
YjU3MTU1MyIsICJ0b29sc19uYW1lcyI6IFtdfV16AhgBhQEAAQAAEo4CChDb0/jP4ZW9RIJxAqKZ
|
||||
qinOEggzWWJgzbM8USoMVGFzayBDcmVhdGVkMAE5mcUVsiSjIhhBz8AWsiSjIhhKLgoIY3Jld19r
|
||||
ZXkSIgogMWYxMjhiZGI3YmFhNGI2NzcxNGYxZGFlZGMyZjNhYjZKMQoHY3Jld19pZBImCiQ0NGUw
|
||||
Y2U0ZC0xZDEyLTRhNWItODI5Mi0yOWQ2OTI5OTcyM2NKLgoIdGFza19rZXkSIgogNmFmYzRiMzk2
|
||||
MjU5ZmJiNzY4MWY1NmM3NzU1Y2M5MzdKMQoHdGFza19pZBImCiQzY2MzYjI1Yy04ZDliLTRiMGEt
|
||||
YTJlZS02Y2M2YjRhZjkwZTR6AhgBhQEAAQAAEo4CChD8o5xENX9GNTwT5q2IoHnoEgiMnCH3dbMf
|
||||
FyoMVGFzayBDcmVhdGVkMAE5a+dntSSjIhhBRXVptSSjIhhKLgoIY3Jld19rZXkSIgogMWYxMjhi
|
||||
ZGI3YmFhNGI2NzcxNGYxZGFlZGMyZjNhYjZKMQoHY3Jld19pZBImCiQ0NGUwY2U0ZC0xZDEyLTRh
|
||||
NWItODI5Mi0yOWQ2OTI5OTcyM2NKLgoIdGFza19rZXkSIgogYjE3YjE4OGRiZjE0ZjkzYTk4ZTVi
|
||||
OTVhYWQzNjc1NzdKMQoHdGFza19pZBImCiQ5MGUxODIyZS00MGU5LTQ1YmItODBkNi00NDcyNDdl
|
||||
OGM5OWR6AhgBhQEAAQAAEpsHChAoyZN/A3mik9oZGmMbKGQtEgiac9/WMXtOjyoMQ3JldyBDcmVh
|
||||
dGVkMAE5lVMVxiSjIhhBgW8nxiSjIhhKGgoOY3Jld2FpX3ZlcnNpb24SCAoGMC44Ni4wShoKDnB5
|
||||
dGhvbl92ZXJzaW9uEggKBjMuMTIuN0ouCghjcmV3X2tleRIiCiA1ZTZlZmZlNjgwYTVkOTdkYzM4
|
||||
NzNiMTQ4MjVjY2ZhM0oxCgdjcmV3X2lkEiYKJDM2NTgyMzlkLWJmYjMtNDg2OC05MjI4LTBlOTBi
|
||||
MzI4YmI5OEocCgxjcmV3X3Byb2Nlc3MSDAoKc2VxdWVudGlhbEoRCgtjcmV3X21lbW9yeRICEABK
|
||||
GgoUY3Jld19udW1iZXJfb2ZfdGFza3MSAhgBShsKFWNyZXdfbnVtYmVyX29mX2FnZW50cxICGAFK
|
||||
zQIKC2NyZXdfYWdlbnRzEr0CCroCW3sia2V5IjogIjkyZTdlYjE5MTY2NGM5MzU3ODVlZDdkNDI0
|
||||
MGEyOTRkIiwgImlkIjogImNhNWEyMjE2LThlYzEtNDk4NS04MjgxLWJiMTkzZjk1ODNlZCIsICJy
|
||||
b2xlIjogIlNjb3JlciIsICJ2ZXJib3NlPyI6IGZhbHNlLCAibWF4X2l0ZXIiOiAyMCwgIm1heF9y
|
||||
cG0iOiBudWxsLCAiZnVuY3Rpb25fY2FsbGluZ19sbG0iOiAiIiwgImxsbSI6ICJncHQtNG8tbWlu
|
||||
aSIsICJkZWxlZ2F0aW9uX2VuYWJsZWQ/IjogZmFsc2UsICJhbGxvd19jb2RlX2V4ZWN1dGlvbj8i
|
||||
OiBmYWxzZSwgIm1heF9yZXRyeV9saW1pdCI6IDIsICJ0b29sc19uYW1lcyI6IFtdfV1K+wEKCmNy
|
||||
ZXdfdGFza3MS7AEK6QFbeyJrZXkiOiAiMjdlZjM4Y2M5OWRhNGE4ZGVkNzBlZDQwNmU0NGFiODYi
|
||||
LCAiaWQiOiAiMzY5NWVjNjctYTIxYy00NGYyLTgyY2EtY2ViZTE1NzUwODc0IiwgImFzeW5jX2V4
|
||||
ZWN1dGlvbj8iOiBmYWxzZSwgImh1bWFuX2lucHV0PyI6IGZhbHNlLCAiYWdlbnRfcm9sZSI6ICJT
|
||||
Y29yZXIiLCAiYWdlbnRfa2V5IjogIjkyZTdlYjE5MTY2NGM5MzU3ODVlZDdkNDI0MGEyOTRkIiwg
|
||||
InRvb2xzX25hbWVzIjogW119XXoCGAGFAQABAAASjgIKEG9C7InGvSd+LDsCFm+mZskSCCbuA/ku
|
||||
smA4KgxUYXNrIENyZWF0ZWQwATmAdUrGJKMiGEG6S0vGJKMiGEouCghjcmV3X2tleRIiCiA1ZTZl
|
||||
ZmZlNjgwYTVkOTdkYzM4NzNiMTQ4MjVjY2ZhM0oxCgdjcmV3X2lkEiYKJDM2NTgyMzlkLWJmYjMt
|
||||
NDg2OC05MjI4LTBlOTBiMzI4YmI5OEouCgh0YXNrX2tleRIiCiAyN2VmMzhjYzk5ZGE0YThkZWQ3
|
||||
MGVkNDA2ZTQ0YWI4NkoxCgd0YXNrX2lkEiYKJDM2OTVlYzY3LWEyMWMtNDRmMi04MmNhLWNlYmUx
|
||||
NTc1MDg3NHoCGAGFAQABAAASnQcKEJ4egRqH6ClfFpC7V2yIMmoSCAVuX0IjxzfSKgxDcmV3IENy
|
||||
ZWF0ZWQwATlCFAPIJKMiGEHFbhTIJKMiGEoaCg5jcmV3YWlfdmVyc2lvbhIICgYwLjg2LjBKGgoO
|
||||
cHl0aG9uX3ZlcnNpb24SCAoGMy4xMi43Si4KCGNyZXdfa2V5EiIKIDVlNmVmZmU2ODBhNWQ5N2Rj
|
||||
Mzg3M2IxNDgyNWNjZmEzSjEKB2NyZXdfaWQSJgokYzBkMTRkYTgtMzgzMy00YzA2LTg0NmUtZTMx
|
||||
YmJiMTgwNWFjSh4KDGNyZXdfcHJvY2VzcxIOCgxoaWVyYXJjaGljYWxKEQoLY3Jld19tZW1vcnkS
|
||||
AhAAShoKFGNyZXdfbnVtYmVyX29mX3Rhc2tzEgIYAUobChVjcmV3X251bWJlcl9vZl9hZ2VudHMS
|
||||
AhgBSs0CCgtjcmV3X2FnZW50cxK9Agq6Alt7ImtleSI6ICI5MmU3ZWIxOTE2NjRjOTM1Nzg1ZWQ3
|
||||
ZDQyNDBhMjk0ZCIsICJpZCI6ICIxNGVkMzU0Yi04ZWI4LTRiYTMtYjhkZC1lM2Q3MTVmODU1NjQi
|
||||
LCAicm9sZSI6ICJTY29yZXIiLCAidmVyYm9zZT8iOiBmYWxzZSwgIm1heF9pdGVyIjogMjAsICJt
|
||||
YXhfcnBtIjogbnVsbCwgImZ1bmN0aW9uX2NhbGxpbmdfbGxtIjogIiIsICJsbG0iOiAiZ3B0LTRv
|
||||
LW1pbmkiLCAiZGVsZWdhdGlvbl9lbmFibGVkPyI6IGZhbHNlLCAiYWxsb3dfY29kZV9leGVjdXRp
|
||||
b24/IjogZmFsc2UsICJtYXhfcmV0cnlfbGltaXQiOiAyLCAidG9vbHNfbmFtZXMiOiBbXX1dSvsB
|
||||
CgpjcmV3X3Rhc2tzEuwBCukBW3sia2V5IjogIjI3ZWYzOGNjOTlkYTRhOGRlZDcwZWQ0MDZlNDRh
|
||||
Yjg2IiwgImlkIjogIjVhYTBlZjViLWU5MDgtNDViOC05MTk2LWZkMDBjMTYwYzU4MSIsICJhc3lu
|
||||
Y19leGVjdXRpb24/IjogZmFsc2UsICJodW1hbl9pbnB1dD8iOiBmYWxzZSwgImFnZW50X3JvbGUi
|
||||
OiAiU2NvcmVyIiwgImFnZW50X2tleSI6ICI5MmU3ZWIxOTE2NjRjOTM1Nzg1ZWQ3ZDQyNDBhMjk0
|
||||
ZCIsICJ0b29sc19uYW1lcyI6IFtdfV16AhgBhQEAAQAAEo4CChB/j2d91vjXCU5eSubkzyxjEgi6
|
||||
KKugA7JaWyoMVGFzayBDcmVhdGVkMAE5T+lQyCSjIhhB08JRyCSjIhhKLgoIY3Jld19rZXkSIgog
|
||||
NWU2ZWZmZTY4MGE1ZDk3ZGMzODczYjE0ODI1Y2NmYTNKMQoHY3Jld19pZBImCiRjMGQxNGRhOC0z
|
||||
ODMzLTRjMDYtODQ2ZS1lMzFiYmIxODA1YWNKLgoIdGFza19rZXkSIgogMjdlZjM4Y2M5OWRhNGE4
|
||||
ZGVkNzBlZDQwNmU0NGFiODZKMQoHdGFza19pZBImCiQ1YWEwZWY1Yi1lOTA4LTQ1YjgtOTE5Ni1m
|
||||
ZDAwYzE2MGM1ODF6AhgBhQEAAQAAEpwBChCkwYvfxd1y9S50Ma7vYDjYEgiQ1VxSLcxPmCoKVG9v
|
||||
bCBVc2FnZTABOUTsXskkoyIYQX21a8kkoyIYShoKDmNyZXdhaV92ZXJzaW9uEggKBjAuODYuMEoo
|
||||
Cgl0b29sX25hbWUSGwoZRGVsZWdhdGUgd29yayB0byBjb3dvcmtlckoOCghhdHRlbXB0cxICGAF6
|
||||
AhgBhQEAAQAAEpsHChCDA1097SLJZyjbOyTH/w6GEgj3Rr0xGU9ywSoMQ3JldyBDcmVhdGVkMAE5
|
||||
cC4RyySjIhhBrSEfyySjIhhKGgoOY3Jld2FpX3ZlcnNpb24SCAoGMC44Ni4wShoKDnB5dGhvbl92
|
||||
ZXJzaW9uEggKBjMuMTIuN0ouCghjcmV3X2tleRIiCiA1ZTZlZmZlNjgwYTVkOTdkYzM4NzNiMTQ4
|
||||
MjVjY2ZhM0oxCgdjcmV3X2lkEiYKJGVkNWE4MjU2LTA0ZGItNDA3Yi1iNTY4LTQ0YmVkZDZjYzEx
|
||||
N0ocCgxjcmV3X3Byb2Nlc3MSDAoKc2VxdWVudGlhbEoRCgtjcmV3X21lbW9yeRICEABKGgoUY3Jl
|
||||
d19udW1iZXJfb2ZfdGFza3MSAhgBShsKFWNyZXdfbnVtYmVyX29mX2FnZW50cxICGAFKzQIKC2Ny
|
||||
ZXdfYWdlbnRzEr0CCroCW3sia2V5IjogIjkyZTdlYjE5MTY2NGM5MzU3ODVlZDdkNDI0MGEyOTRk
|
||||
IiwgImlkIjogIjg2MmZlZDY3LTEzZTctNDI4ZS1hZGZlLWY5NDJiNmRhZTIwZCIsICJyb2xlIjog
|
||||
IlNjb3JlciIsICJ2ZXJib3NlPyI6IGZhbHNlLCAibWF4X2l0ZXIiOiAyMCwgIm1heF9ycG0iOiBu
|
||||
dWxsLCAiZnVuY3Rpb25fY2FsbGluZ19sbG0iOiAiIiwgImxsbSI6ICJncHQtNG8tbWluaSIsICJk
|
||||
ZWxlZ2F0aW9uX2VuYWJsZWQ/IjogZmFsc2UsICJhbGxvd19jb2RlX2V4ZWN1dGlvbj8iOiBmYWxz
|
||||
ZSwgIm1heF9yZXRyeV9saW1pdCI6IDIsICJ0b29sc19uYW1lcyI6IFtdfV1K+wEKCmNyZXdfdGFz
|
||||
a3MS7AEK6QFbeyJrZXkiOiAiMjdlZjM4Y2M5OWRhNGE4ZGVkNzBlZDQwNmU0NGFiODYiLCAiaWQi
|
||||
OiAiZjBmMWJkOTItMDY0Mi00NzU2LThlNjMtODkxZjlmOTQ5ODdjIiwgImFzeW5jX2V4ZWN1dGlv
|
||||
bj8iOiBmYWxzZSwgImh1bWFuX2lucHV0PyI6IGZhbHNlLCAiYWdlbnRfcm9sZSI6ICJTY29yZXIi
|
||||
LCAiYWdlbnRfa2V5IjogIjkyZTdlYjE5MTY2NGM5MzU3ODVlZDdkNDI0MGEyOTRkIiwgInRvb2xz
|
||||
X25hbWVzIjogW119XXoCGAGFAQABAAASjgIKEJfhw9QQsm5oO4m34HPYKYwSCDwQBNXO4nndKgxU
|
||||
YXNrIENyZWF0ZWQwATnvnEzLJKMiGEHMb03LJKMiGEouCghjcmV3X2tleRIiCiA1ZTZlZmZlNjgw
|
||||
YTVkOTdkYzM4NzNiMTQ4MjVjY2ZhM0oxCgdjcmV3X2lkEiYKJGVkNWE4MjU2LTA0ZGItNDA3Yi1i
|
||||
NTY4LTQ0YmVkZDZjYzExN0ouCgh0YXNrX2tleRIiCiAyN2VmMzhjYzk5ZGE0YThkZWQ3MGVkNDA2
|
||||
ZTQ0YWI4NkoxCgd0YXNrX2lkEiYKJGYwZjFiZDkyLTA2NDItNDc1Ni04ZTYzLTg5MWY5Zjk0OTg3
|
||||
Y3oCGAGFAQABAAASnQcKEIH2iL8MwCyxciv7DijtWuESCBXqivSWJRr4KgxDcmV3IENyZWF0ZWQw
|
||||
ATm59/7MJKMiGEFTchDNJKMiGEoaCg5jcmV3YWlfdmVyc2lvbhIICgYwLjg2LjBKGgoOcHl0aG9u
|
||||
X3ZlcnNpb24SCAoGMy4xMi43Si4KCGNyZXdfa2V5EiIKIDVlNmVmZmU2ODBhNWQ5N2RjMzg3M2Ix
|
||||
NDgyNWNjZmEzSjEKB2NyZXdfaWQSJgokNDViOGZkMDEtMTVhNy00NDI1LTkwY2MtNzZlZWY5NGJm
|
||||
MjQ2Sh4KDGNyZXdfcHJvY2VzcxIOCgxoaWVyYXJjaGljYWxKEQoLY3Jld19tZW1vcnkSAhAAShoK
|
||||
FGNyZXdfbnVtYmVyX29mX3Rhc2tzEgIYAUobChVjcmV3X251bWJlcl9vZl9hZ2VudHMSAhgBSs0C
|
||||
CgtjcmV3X2FnZW50cxK9Agq6Alt7ImtleSI6ICI5MmU3ZWIxOTE2NjRjOTM1Nzg1ZWQ3ZDQyNDBh
|
||||
Mjk0ZCIsICJpZCI6ICI4NzI5MmI5NS04ZjYzLTQyNWMtYjgxYi00NjUyMzM5ZDZjNzQiLCAicm9s
|
||||
ZSI6ICJTY29yZXIiLCAidmVyYm9zZT8iOiBmYWxzZSwgIm1heF9pdGVyIjogMjAsICJtYXhfcnBt
|
||||
IjogbnVsbCwgImZ1bmN0aW9uX2NhbGxpbmdfbGxtIjogIiIsICJsbG0iOiAiZ3B0LTRvLW1pbmki
|
||||
LCAiZGVsZWdhdGlvbl9lbmFibGVkPyI6IGZhbHNlLCAiYWxsb3dfY29kZV9leGVjdXRpb24/Ijog
|
||||
ZmFsc2UsICJtYXhfcmV0cnlfbGltaXQiOiAyLCAidG9vbHNfbmFtZXMiOiBbXX1dSvsBCgpjcmV3
|
||||
X3Rhc2tzEuwBCukBW3sia2V5IjogIjI3ZWYzOGNjOTlkYTRhOGRlZDcwZWQ0MDZlNDRhYjg2Iiwg
|
||||
ImlkIjogIjI0YTM2ZWExLTI1YWQtNDU1OS1iMzkxLWM2MjYwNDk3YjhjZSIsICJhc3luY19leGVj
|
||||
dXRpb24/IjogZmFsc2UsICJodW1hbl9pbnB1dD8iOiBmYWxzZSwgImFnZW50X3JvbGUiOiAiU2Nv
|
||||
cmVyIiwgImFnZW50X2tleSI6ICI5MmU3ZWIxOTE2NjRjOTM1Nzg1ZWQ3ZDQyNDBhMjk0ZCIsICJ0
|
||||
b29sc19uYW1lcyI6IFtdfV16AhgBhQEAAQAAEo4CChClS2LbYBiEyGulBRO7WWgQEghpRbsqrqdI
|
||||
DioMVGFzayBDcmVhdGVkMAE57wxUzSSjIhhBDuhUzSSjIhhKLgoIY3Jld19rZXkSIgogNWU2ZWZm
|
||||
ZTY4MGE1ZDk3ZGMzODczYjE0ODI1Y2NmYTNKMQoHY3Jld19pZBImCiQ0NWI4ZmQwMS0xNWE3LTQ0
|
||||
MjUtOTBjYy03NmVlZjk0YmYyNDZKLgoIdGFza19rZXkSIgogMjdlZjM4Y2M5OWRhNGE4ZGVkNzBl
|
||||
ZDQwNmU0NGFiODZKMQoHdGFza19pZBImCiQyNGEzNmVhMS0yNWFkLTQ1NTktYjM5MS1jNjI2MDQ5
|
||||
N2I4Y2V6AhgBhQEAAQAAEpsBChDN77UQGIcr2bmJLGhUJJOUEgh1d9JM0p49rSoKVG9vbCBVc2Fn
|
||||
ZTABOUOWXs4koyIYQbGtas4koyIYShoKDmNyZXdhaV92ZXJzaW9uEggKBjAuODYuMEonCgl0b29s
|
||||
X25hbWUSGgoYQXNrIHF1ZXN0aW9uIHRvIGNvd29ya2VySg4KCGF0dGVtcHRzEgIYAXoCGAGFAQAB
|
||||
AAASmwcKEK4sHtlSv49kxk3PNgpUJm8SCDF6poPyohPMKgxDcmV3IENyZWF0ZWQwATlZ4wjQJKMi
|
||||
GEHm1hbQJKMiGEoaCg5jcmV3YWlfdmVyc2lvbhIICgYwLjg2LjBKGgoOcHl0aG9uX3ZlcnNpb24S
|
||||
CAoGMy4xMi43Si4KCGNyZXdfa2V5EiIKIDVlNmVmZmU2ODBhNWQ5N2RjMzg3M2IxNDgyNWNjZmEz
|
||||
SjEKB2NyZXdfaWQSJgokNWNiYjNjMTUtODVkZS00MmI3LTgzMDktNzE5ZDlkNDJhNzQwShwKDGNy
|
||||
ZXdfcHJvY2VzcxIMCgpzZXF1ZW50aWFsShEKC2NyZXdfbWVtb3J5EgIQAEoaChRjcmV3X251bWJl
|
||||
cl9vZl90YXNrcxICGAFKGwoVY3Jld19udW1iZXJfb2ZfYWdlbnRzEgIYAUrNAgoLY3Jld19hZ2Vu
|
||||
dHMSvQIKugJbeyJrZXkiOiAiOTJlN2ViMTkxNjY0YzkzNTc4NWVkN2Q0MjQwYTI5NGQiLCAiaWQi
|
||||
OiAiYWJlY2EyY2YtOGQ3My00ZmQ2LThkNDQtOTA0MzBhZTY4YmM5IiwgInJvbGUiOiAiU2NvcmVy
|
||||
IiwgInZlcmJvc2U/IjogZmFsc2UsICJtYXhfaXRlciI6IDIwLCAibWF4X3JwbSI6IG51bGwsICJm
|
||||
dW5jdGlvbl9jYWxsaW5nX2xsbSI6ICIiLCAibGxtIjogImdwdC00by1taW5pIiwgImRlbGVnYXRp
|
||||
b25fZW5hYmxlZD8iOiBmYWxzZSwgImFsbG93X2NvZGVfZXhlY3V0aW9uPyI6IGZhbHNlLCAibWF4
|
||||
X3JldHJ5X2xpbWl0IjogMiwgInRvb2xzX25hbWVzIjogW119XUr7AQoKY3Jld190YXNrcxLsAQrp
|
||||
AVt7ImtleSI6ICIyN2VmMzhjYzk5ZGE0YThkZWQ3MGVkNDA2ZTQ0YWI4NiIsICJpZCI6ICJkNGIx
|
||||
ZTQyYS0xNmFjLTQ1ZjMtOTI1Ni03OGM5MjkxZWIxMDMiLCAiYXN5bmNfZXhlY3V0aW9uPyI6IGZh
|
||||
bHNlLCAiaHVtYW5faW5wdXQ/IjogZmFsc2UsICJhZ2VudF9yb2xlIjogIlNjb3JlciIsICJhZ2Vu
|
||||
dF9rZXkiOiAiOTJlN2ViMTkxNjY0YzkzNTc4NWVkN2Q0MjQwYTI5NGQiLCAidG9vbHNfbmFtZXMi
|
||||
OiBbXX1degIYAYUBAAEAABKOAgoQbcfwcuHajgZhUJL3KYPQORIIbQy6sHdKT/kqDFRhc2sgQ3Jl
|
||||
YXRlZDABOSNLPdAkoyIYQZsfPtAkoyIYSi4KCGNyZXdfa2V5EiIKIDVlNmVmZmU2ODBhNWQ5N2Rj
|
||||
Mzg3M2IxNDgyNWNjZmEzSjEKB2NyZXdfaWQSJgokNWNiYjNjMTUtODVkZS00MmI3LTgzMDktNzE5
|
||||
ZDlkNDJhNzQwSi4KCHRhc2tfa2V5EiIKIDI3ZWYzOGNjOTlkYTRhOGRlZDcwZWQ0MDZlNDRhYjg2
|
||||
SjEKB3Rhc2tfaWQSJgokZDRiMWU0MmEtMTZhYy00NWYzLTkyNTYtNzhjOTI5MWViMTAzegIYAYUB
|
||||
AAEAABKbBwoQ9ep4lJz8D9//6aykqVdJihIIoYjslBwzS7sqDENyZXcgQ3JlYXRlZDABOTKg5dEk
|
||||
oyIYQVVu89EkoyIYShoKDmNyZXdhaV92ZXJzaW9uEggKBjAuODYuMEoaCg5weXRob25fdmVyc2lv
|
||||
bhIICgYzLjEyLjdKLgoIY3Jld19rZXkSIgogNWU2ZWZmZTY4MGE1ZDk3ZGMzODczYjE0ODI1Y2Nm
|
||||
YTNKMQoHY3Jld19pZBImCiQ5MTg5ZWE3Ny1jM2I0LTQ4ZTYtYTFjZC0zNWE2ZjcxZTI4ZGFKHAoM
|
||||
Y3Jld19wcm9jZXNzEgwKCnNlcXVlbnRpYWxKEQoLY3Jld19tZW1vcnkSAhAAShoKFGNyZXdfbnVt
|
||||
YmVyX29mX3Rhc2tzEgIYAUobChVjcmV3X251bWJlcl9vZl9hZ2VudHMSAhgBSs0CCgtjcmV3X2Fn
|
||||
ZW50cxK9Agq6Alt7ImtleSI6ICI5MmU3ZWIxOTE2NjRjOTM1Nzg1ZWQ3ZDQyNDBhMjk0ZCIsICJp
|
||||
ZCI6ICI5MjQzNmFiNy1jZWIyLTRhMzUtYTBlMS1iY2Q3ZjBkNDhkOWIiLCAicm9sZSI6ICJTY29y
|
||||
ZXIiLCAidmVyYm9zZT8iOiBmYWxzZSwgIm1heF9pdGVyIjogMjAsICJtYXhfcnBtIjogbnVsbCwg
|
||||
ImZ1bmN0aW9uX2NhbGxpbmdfbGxtIjogIiIsICJsbG0iOiAiZ3B0LTRvLW1pbmkiLCAiZGVsZWdh
|
||||
dGlvbl9lbmFibGVkPyI6IGZhbHNlLCAiYWxsb3dfY29kZV9leGVjdXRpb24/IjogZmFsc2UsICJt
|
||||
YXhfcmV0cnlfbGltaXQiOiAyLCAidG9vbHNfbmFtZXMiOiBbXX1dSvsBCgpjcmV3X3Rhc2tzEuwB
|
||||
CukBW3sia2V5IjogIjI3ZWYzOGNjOTlkYTRhOGRlZDcwZWQ0MDZlNDRhYjg2IiwgImlkIjogIjc4
|
||||
YjliNjAwLTY4NzQtNGVmNS1hMWU3LTdjMmUwNTBlYWE2NCIsICJhc3luY19leGVjdXRpb24/Ijog
|
||||
ZmFsc2UsICJodW1hbl9pbnB1dD8iOiBmYWxzZSwgImFnZW50X3JvbGUiOiAiU2NvcmVyIiwgImFn
|
||||
ZW50X2tleSI6ICI5MmU3ZWIxOTE2NjRjOTM1Nzg1ZWQ3ZDQyNDBhMjk0ZCIsICJ0b29sc19uYW1l
|
||||
cyI6IFtdfV16AhgBhQEAAQAAEo4CChB6kdr6+4/CB2JSTi+vWEo7EgjAmap0Xcx4YSoMVGFzayBD
|
||||
cmVhdGVkMAE5/3Qh0iSjIhhB2Lkj0iSjIhhKLgoIY3Jld19rZXkSIgogNWU2ZWZmZTY4MGE1ZDk3
|
||||
ZGMzODczYjE0ODI1Y2NmYTNKMQoHY3Jld19pZBImCiQ5MTg5ZWE3Ny1jM2I0LTQ4ZTYtYTFjZC0z
|
||||
NWE2ZjcxZTI4ZGFKLgoIdGFza19rZXkSIgogMjdlZjM4Y2M5OWRhNGE4ZGVkNzBlZDQwNmU0NGFi
|
||||
ODZKMQoHdGFza19pZBImCiQ3OGI5YjYwMC02ODc0LTRlZjUtYTFlNy03YzJlMDUwZWFhNjR6AhgB
|
||||
hQEAAQAAEp0HChAUlS712UNXW/JeCmAoSjYGEgg5R7hVBwToxSoMQ3JldyBDcmVhdGVkMAE5ZuTZ
|
||||
0ySjIhhBFLXq0ySjIhhKGgoOY3Jld2FpX3ZlcnNpb24SCAoGMC44Ni4wShoKDnB5dGhvbl92ZXJz
|
||||
aW9uEggKBjMuMTIuN0ouCghjcmV3X2tleRIiCiA1ZTZlZmZlNjgwYTVkOTdkYzM4NzNiMTQ4MjVj
|
||||
Y2ZhM0oxCgdjcmV3X2lkEiYKJDhhNGI1YWFjLTdiNjYtNGY2MC05NTBhLTVlMGY3NzhhMWNkN0oe
|
||||
CgxjcmV3X3Byb2Nlc3MSDgoMaGllcmFyY2hpY2FsShEKC2NyZXdfbWVtb3J5EgIQAEoaChRjcmV3
|
||||
X251bWJlcl9vZl90YXNrcxICGAFKGwoVY3Jld19udW1iZXJfb2ZfYWdlbnRzEgIYAUrNAgoLY3Jl
|
||||
d19hZ2VudHMSvQIKugJbeyJrZXkiOiAiOTJlN2ViMTkxNjY0YzkzNTc4NWVkN2Q0MjQwYTI5NGQi
|
||||
LCAiaWQiOiAiNzE5OTYwZGEtOTVmZi00NzI3LTlmNGUtNDU1NjQwNGQ2ZjZkIiwgInJvbGUiOiAi
|
||||
U2NvcmVyIiwgInZlcmJvc2U/IjogZmFsc2UsICJtYXhfaXRlciI6IDIwLCAibWF4X3JwbSI6IG51
|
||||
bGwsICJmdW5jdGlvbl9jYWxsaW5nX2xsbSI6ICIiLCAibGxtIjogImdwdC00by1taW5pIiwgImRl
|
||||
bGVnYXRpb25fZW5hYmxlZD8iOiBmYWxzZSwgImFsbG93X2NvZGVfZXhlY3V0aW9uPyI6IGZhbHNl
|
||||
LCAibWF4X3JldHJ5X2xpbWl0IjogMiwgInRvb2xzX25hbWVzIjogW119XUr7AQoKY3Jld190YXNr
|
||||
cxLsAQrpAVt7ImtleSI6ICIyN2VmMzhjYzk5ZGE0YThkZWQ3MGVkNDA2ZTQ0YWI4NiIsICJpZCI6
|
||||
ICI2NGRkOTE0Mi1iZGRjLTQ5MGUtODliYy1kOWE0YzE2YjQxODciLCAiYXN5bmNfZXhlY3V0aW9u
|
||||
PyI6IGZhbHNlLCAiaHVtYW5faW5wdXQ/IjogZmFsc2UsICJhZ2VudF9yb2xlIjogIlNjb3JlciIs
|
||||
ICJhZ2VudF9rZXkiOiAiOTJlN2ViMTkxNjY0YzkzNTc4NWVkN2Q0MjQwYTI5NGQiLCAidG9vbHNf
|
||||
bmFtZXMiOiBbXX1degIYAYUBAAEAABKOAgoQW4UG23mvxeRRQT2Zuaro9xIIexad+ZdTo7oqDFRh
|
||||
c2sgQ3JlYXRlZDABORiwKtQkoyIYQZCNK9QkoyIYSi4KCGNyZXdfa2V5EiIKIDVlNmVmZmU2ODBh
|
||||
NWQ5N2RjMzg3M2IxNDgyNWNjZmEzSjEKB2NyZXdfaWQSJgokOGE0YjVhYWMtN2I2Ni00ZjYwLTk1
|
||||
MGEtNWUwZjc3OGExY2Q3Si4KCHRhc2tfa2V5EiIKIDI3ZWYzOGNjOTlkYTRhOGRlZDcwZWQ0MDZl
|
||||
NDRhYjg2SjEKB3Rhc2tfaWQSJgokNjRkZDkxNDItYmRkYy00OTBlLTg5YmMtZDlhNGMxNmI0MTg3
|
||||
egIYAYUBAAEAABKbAQoQ0w+xTeI87bGpdrKWvSsgcxIImh2g+d0tglkqClRvb2wgVXNhZ2UwATkk
|
||||
WFbVJKMiGEF322LVJKMiGEoaCg5jcmV3YWlfdmVyc2lvbhIICgYwLjg2LjBKJwoJdG9vbF9uYW1l
|
||||
EhoKGEFzayBxdWVzdGlvbiB0byBjb3dvcmtlckoOCghhdHRlbXB0cxICGAF6AhgBhQEAAQAAEpwJ
|
||||
ChBqpyAQAgaTBeE7Dj5L+CwUEgibQZW88Ea6iSoMQ3JldyBDcmVhdGVkMAE5aqgY1ySjIhhBCGsn
|
||||
1ySjIhhKGgoOY3Jld2FpX3ZlcnNpb24SCAoGMC44Ni4wShoKDnB5dGhvbl92ZXJzaW9uEggKBjMu
|
||||
MTIuN0ouCghjcmV3X2tleRIiCiBkNDI2MDgzM2FiMGMyMGJiNDQ5MjJjNzk5YWE5NmI0YUoxCgdj
|
||||
cmV3X2lkEiYKJDAxZDVmZjliLWQ3NzUtNDljNS1iYWNiLTllN2M2NWI2YjBlMUocCgxjcmV3X3By
|
||||
b2Nlc3MSDAoKc2VxdWVudGlhbEoRCgtjcmV3X21lbW9yeRICEABKGgoUY3Jld19udW1iZXJfb2Zf
|
||||
dGFza3MSAhgCShsKFWNyZXdfbnVtYmVyX29mX2FnZW50cxICGAFK5QIKC2NyZXdfYWdlbnRzEtUC
|
||||
CtICW3sia2V5IjogIjkyZTdlYjE5MTY2NGM5MzU3ODVlZDdkNDI0MGEyOTRkIiwgImlkIjogIjk3
|
||||
Yzc2ODgxLWUwOTAtNGY4Yy1iZjJlLThhNGM1Yjg4MzExYSIsICJyb2xlIjogIlNjb3JlciIsICJ2
|
||||
ZXJib3NlPyI6IHRydWUsICJtYXhfaXRlciI6IDIwLCAibWF4X3JwbSI6IG51bGwsICJmdW5jdGlv
|
||||
bl9jYWxsaW5nX2xsbSI6ICJncHQtMy41LXR1cmJvLTAxMjUiLCAibGxtIjogImdwdC00LTAxMjUt
|
||||
cHJldmlldyIsICJkZWxlZ2F0aW9uX2VuYWJsZWQ/IjogZmFsc2UsICJhbGxvd19jb2RlX2V4ZWN1
|
||||
dGlvbj8iOiBmYWxzZSwgIm1heF9yZXRyeV9saW1pdCI6IDIsICJ0b29sc19uYW1lcyI6IFtdfV1K
|
||||
5AMKCmNyZXdfdGFza3MS1QMK0gNbeyJrZXkiOiAiMjdlZjM4Y2M5OWRhNGE4ZGVkNzBlZDQwNmU0
|
||||
NGFiODYiLCAiaWQiOiAiYmZhMjhiZDQtYTk3Ny00MGQzLTg0ODgtNDQ1OTUxNTljYjBiIiwgImFz
|
||||
eW5jX2V4ZWN1dGlvbj8iOiBmYWxzZSwgImh1bWFuX2lucHV0PyI6IGZhbHNlLCAiYWdlbnRfcm9s
|
||||
ZSI6ICJTY29yZXIiLCAiYWdlbnRfa2V5IjogIjkyZTdlYjE5MTY2NGM5MzU3ODVlZDdkNDI0MGEy
|
||||
OTRkIiwgInRvb2xzX25hbWVzIjogW119LCB7ImtleSI6ICI2MDlkZWUzOTEwODhjZDFjODdiOGZh
|
||||
NjZhYTY3YWRiZSIsICJpZCI6ICI4NGZhZjg3MC1mYWEzLTQ5OWUtYWU0MC0yMmQwYTFkMGU2ZGIi
|
||||
LCAiYXN5bmNfZXhlY3V0aW9uPyI6IGZhbHNlLCAiaHVtYW5faW5wdXQ/IjogZmFsc2UsICJhZ2Vu
|
||||
dF9yb2xlIjogIlNjb3JlciIsICJhZ2VudF9rZXkiOiAiOTJlN2ViMTkxNjY0YzkzNTc4NWVkN2Q0
|
||||
MjQwYTI5NGQiLCAidG9vbHNfbmFtZXMiOiBbXX1degIYAYUBAAEAABKOAgoQbtOsbDPillwMbqtc
|
||||
UFtatxIIpNDcL/9RJ+wqDFRhc2sgQ3JlYXRlZDABOTVaTdckoyIYQSpCTtckoyIYSi4KCGNyZXdf
|
||||
a2V5EiIKIGQ0MjYwODMzYWIwYzIwYmI0NDkyMmM3OTlhYTk2YjRhSjEKB2NyZXdfaWQSJgokMDFk
|
||||
NWZmOWItZDc3NS00OWM1LWJhY2ItOWU3YzY1YjZiMGUxSi4KCHRhc2tfa2V5EiIKIDI3ZWYzOGNj
|
||||
OTlkYTRhOGRlZDcwZWQ0MDZlNDRhYjg2SjEKB3Rhc2tfaWQSJgokYmZhMjhiZDQtYTk3Ny00MGQz
|
||||
LTg0ODgtNDQ1OTUxNTljYjBiegIYAYUBAAEAABKOAgoQ6X/lrVO6W/1W78gXkV/aahII2Z9M4UtV
|
||||
SlEqDFRhc2sgQ3JlYXRlZDABOY3Xc9gkoyIYQQl4ddgkoyIYSi4KCGNyZXdfa2V5EiIKIGQ0MjYw
|
||||
ODMzYWIwYzIwYmI0NDkyMmM3OTlhYTk2YjRhSjEKB2NyZXdfaWQSJgokMDFkNWZmOWItZDc3NS00
|
||||
OWM1LWJhY2ItOWU3YzY1YjZiMGUxSi4KCHRhc2tfa2V5EiIKIDYwOWRlZTM5MTA4OGNkMWM4N2I4
|
||||
ZmE2NmFhNjdhZGJlSjEKB3Rhc2tfaWQSJgokODRmYWY4NzAtZmFhMy00OTllLWFlNDAtMjJkMGEx
|
||||
ZDBlNmRiegIYAYUBAAEAABKECQoQ4sTA9bnS4aK77FmZoTw92hIIazwK5mTztlQqDENyZXcgQ3Jl
|
||||
YXRlZDABOTzBKNokoyIYQWLpNtokoyIYShoKDmNyZXdhaV92ZXJzaW9uEggKBjAuODYuMEoaCg5w
|
||||
eXRob25fdmVyc2lvbhIICgYzLjEyLjdKLgoIY3Jld19rZXkSIgogYTk1NDBjZDBlYWE1M2Y2NzU0
|
||||
MzdlOWJkNGZhNWU0NGNKMQoHY3Jld19pZBImCiQzMDEzOWM5Yy00MjIzLTRhMmYtYjZiNS00ZjAy
|
||||
NWUzNGY0MjRKHAoMY3Jld19wcm9jZXNzEgwKCnNlcXVlbnRpYWxKEQoLY3Jld19tZW1vcnkSAhAA
|
||||
ShoKFGNyZXdfbnVtYmVyX29mX3Rhc2tzEgIYAkobChVjcmV3X251bWJlcl9vZl9hZ2VudHMSAhgB
|
||||
Ss0CCgtjcmV3X2FnZW50cxK9Agq6Alt7ImtleSI6ICI5MmU3ZWIxOTE2NjRjOTM1Nzg1ZWQ3ZDQy
|
||||
NDBhMjk0ZCIsICJpZCI6ICJhZDljNTBkZS0zOGI0LTRiYzItOWM1My02ZjAxZTc0YzlhZTUiLCAi
|
||||
cm9sZSI6ICJTY29yZXIiLCAidmVyYm9zZT8iOiBmYWxzZSwgIm1heF9pdGVyIjogMjAsICJtYXhf
|
||||
cnBtIjogbnVsbCwgImZ1bmN0aW9uX2NhbGxpbmdfbGxtIjogIiIsICJsbG0iOiAiZ3B0LTRvLW1p
|
||||
bmkiLCAiZGVsZWdhdGlvbl9lbmFibGVkPyI6IGZhbHNlLCAiYWxsb3dfY29kZV9leGVjdXRpb24/
|
||||
IjogZmFsc2UsICJtYXhfcmV0cnlfbGltaXQiOiAyLCAidG9vbHNfbmFtZXMiOiBbXX1dSuQDCgpj
|
||||
cmV3X3Rhc2tzEtUDCtIDW3sia2V5IjogIjI3ZWYzOGNjOTlkYTRhOGRlZDcwZWQ0MDZlNDRhYjg2
|
||||
IiwgImlkIjogIjM0NDg2MzU2LWU1MDktNDFhMC05MmYxLTU0NzcxYjk0MDVjMSIsICJhc3luY19l
|
||||
eGVjdXRpb24/IjogZmFsc2UsICJodW1hbl9pbnB1dD8iOiBmYWxzZSwgImFnZW50X3JvbGUiOiAi
|
||||
U2NvcmVyIiwgImFnZW50X2tleSI6ICI5MmU3ZWIxOTE2NjRjOTM1Nzg1ZWQ3ZDQyNDBhMjk0ZCIs
|
||||
ICJ0b29sc19uYW1lcyI6IFtdfSwgeyJrZXkiOiAiYjBkMzRhNmY2MjFhN2IzNTgwZDVkMWY0ZTI2
|
||||
NjViOTIiLCAiaWQiOiAiMWY0NTc1ZjItYzA2My00OTYwLWIyZWUtN2FmMDUxMDMzZWFmIiwgImFz
|
||||
eW5jX2V4ZWN1dGlvbj8iOiBmYWxzZSwgImh1bWFuX2lucHV0PyI6IGZhbHNlLCAiYWdlbnRfcm9s
|
||||
ZSI6ICJTY29yZXIiLCAiYWdlbnRfa2V5IjogIjkyZTdlYjE5MTY2NGM5MzU3ODVlZDdkNDI0MGEy
|
||||
OTRkIiwgInRvb2xzX25hbWVzIjogW119XXoCGAGFAQABAAASjgIKEIy86sxMK7HH6dXvQg81kNES
|
||||
CLe/dx1p+O8aKgxUYXNrIENyZWF0ZWQwATkT2VnaJKMiGEELu1raJKMiGEouCghjcmV3X2tleRIi
|
||||
CiBhOTU0MGNkMGVhYTUzZjY3NTQzN2U5YmQ0ZmE1ZTQ0Y0oxCgdjcmV3X2lkEiYKJDMwMTM5Yzlj
|
||||
LTQyMjMtNGEyZi1iNmI1LTRmMDI1ZTM0ZjQyNEouCgh0YXNrX2tleRIiCiAyN2VmMzhjYzk5ZGE0
|
||||
YThkZWQ3MGVkNDA2ZTQ0YWI4NkoxCgd0YXNrX2lkEiYKJDM0NDg2MzU2LWU1MDktNDFhMC05MmYx
|
||||
LTU0NzcxYjk0MDVjMXoCGAGFAQABAAASjgIKEEIy6EUZOks++FCcxCgFznkSCH6Pcxc2UJBUKgxU
|
||||
YXNrIENyZWF0ZWQwATm1tHfbJKMiGEFZsHjbJKMiGEouCghjcmV3X2tleRIiCiBhOTU0MGNkMGVh
|
||||
YTUzZjY3NTQzN2U5YmQ0ZmE1ZTQ0Y0oxCgdjcmV3X2lkEiYKJDMwMTM5YzljLTQyMjMtNGEyZi1i
|
||||
NmI1LTRmMDI1ZTM0ZjQyNEouCgh0YXNrX2tleRIiCiBiMGQzNGE2ZjYyMWE3YjM1ODBkNWQxZjRl
|
||||
MjY2NWI5MkoxCgd0YXNrX2lkEiYKJDFmNDU3NWYyLWMwNjMtNDk2MC1iMmVlLTdhZjA1MTAzM2Vh
|
||||
ZnoCGAGFAQABAAASmwcKEBq1KipKQwx6KffBT4LKfNkSCIrByvPScTCiKgxDcmV3IENyZWF0ZWQw
|
||||
ATmIJPfcJKMiGEHNGwXdJKMiGEoaCg5jcmV3YWlfdmVyc2lvbhIICgYwLjg2LjBKGgoOcHl0aG9u
|
||||
X3ZlcnNpb24SCAoGMy4xMi43Si4KCGNyZXdfa2V5EiIKIDVlNmVmZmU2ODBhNWQ5N2RjMzg3M2Ix
|
||||
NDgyNWNjZmEzSjEKB2NyZXdfaWQSJgokMGRjYTM3Y2ItMDQyZS00YjgzLTgwOGMtZWUxNTdmN2Y0
|
||||
ZmM2ShwKDGNyZXdfcHJvY2VzcxIMCgpzZXF1ZW50aWFsShEKC2NyZXdfbWVtb3J5EgIQAEoaChRj
|
||||
cmV3X251bWJlcl9vZl90YXNrcxICGAFKGwoVY3Jld19udW1iZXJfb2ZfYWdlbnRzEgIYAUrNAgoL
|
||||
Y3Jld19hZ2VudHMSvQIKugJbeyJrZXkiOiAiOTJlN2ViMTkxNjY0YzkzNTc4NWVkN2Q0MjQwYTI5
|
||||
NGQiLCAiaWQiOiAiOTViZTM5MjgtNjM4Ni00YmE1LWIxNTItODkxNTg1NzVmNDNlIiwgInJvbGUi
|
||||
OiAiU2NvcmVyIiwgInZlcmJvc2U/IjogZmFsc2UsICJtYXhfaXRlciI6IDIwLCAibWF4X3JwbSI6
|
||||
IG51bGwsICJmdW5jdGlvbl9jYWxsaW5nX2xsbSI6ICIiLCAibGxtIjogImdwdC00by1taW5pIiwg
|
||||
ImRlbGVnYXRpb25fZW5hYmxlZD8iOiBmYWxzZSwgImFsbG93X2NvZGVfZXhlY3V0aW9uPyI6IGZh
|
||||
bHNlLCAibWF4X3JldHJ5X2xpbWl0IjogMiwgInRvb2xzX25hbWVzIjogW119XUr7AQoKY3Jld190
|
||||
YXNrcxLsAQrpAVt7ImtleSI6ICIyN2VmMzhjYzk5ZGE0YThkZWQ3MGVkNDA2ZTQ0YWI4NiIsICJp
|
||||
ZCI6ICI4NWQxOGRmYi1mZTM4LTQ3ZTgtYjNmZS0wMTc2MzVjMjNhYjIiLCAiYXN5bmNfZXhlY3V0
|
||||
aW9uPyI6IGZhbHNlLCAiaHVtYW5faW5wdXQ/IjogZmFsc2UsICJhZ2VudF9yb2xlIjogIlNjb3Jl
|
||||
ciIsICJhZ2VudF9rZXkiOiAiOTJlN2ViMTkxNjY0YzkzNTc4NWVkN2Q0MjQwYTI5NGQiLCAidG9v
|
||||
bHNfbmFtZXMiOiBbXX1degIYAYUBAAEAABKOAgoQJ+5h/x8Yo+r+8SizOliH1BIIFTv8E8vath0q
|
||||
DFRhc2sgQ3JlYXRlZDABOVd7KN0koyIYQQdWKd0koyIYSi4KCGNyZXdfa2V5EiIKIDVlNmVmZmU2
|
||||
ODBhNWQ5N2RjMzg3M2IxNDgyNWNjZmEzSjEKB2NyZXdfaWQSJgokMGRjYTM3Y2ItMDQyZS00Yjgz
|
||||
LTgwOGMtZWUxNTdmN2Y0ZmM2Si4KCHRhc2tfa2V5EiIKIDI3ZWYzOGNjOTlkYTRhOGRlZDcwZWQ0
|
||||
MDZlNDRhYjg2SjEKB3Rhc2tfaWQSJgokODVkMThkZmItZmUzOC00N2U4LWIzZmUtMDE3NjM1YzIz
|
||||
YWIyegIYAYUBAAEAABKbBwoQb5W37I/KxV/nd7VDeDBIVhIIAENUVnXaw5kqDENyZXcgQ3JlYXRl
|
||||
ZDABOQlUM94koyIYQSTHQ94koyIYShoKDmNyZXdhaV92ZXJzaW9uEggKBjAuODYuMEoaCg5weXRo
|
||||
b25fdmVyc2lvbhIICgYzLjEyLjdKLgoIY3Jld19rZXkSIgogNWU2ZWZmZTY4MGE1ZDk3ZGMzODcz
|
||||
YjE0ODI1Y2NmYTNKMQoHY3Jld19pZBImCiRiZjg5ZmNlZC03ZmQwLTRjYmMtOTMxZi01NGU5ZmRk
|
||||
NGI3NWFKHAoMY3Jld19wcm9jZXNzEgwKCnNlcXVlbnRpYWxKEQoLY3Jld19tZW1vcnkSAhAAShoK
|
||||
FGNyZXdfbnVtYmVyX29mX3Rhc2tzEgIYAUobChVjcmV3X251bWJlcl9vZl9hZ2VudHMSAhgBSs0C
|
||||
CgtjcmV3X2FnZW50cxK9Agq6Alt7ImtleSI6ICI5MmU3ZWIxOTE2NjRjOTM1Nzg1ZWQ3ZDQyNDBh
|
||||
Mjk0ZCIsICJpZCI6ICJlNWU1M2UxNy05M2Y4LTQ3MTAtYjdiMS0xYWIzOGM2MGVlMzYiLCAicm9s
|
||||
ZSI6ICJTY29yZXIiLCAidmVyYm9zZT8iOiBmYWxzZSwgIm1heF9pdGVyIjogMjAsICJtYXhfcnBt
|
||||
IjogbnVsbCwgImZ1bmN0aW9uX2NhbGxpbmdfbGxtIjogIiIsICJsbG0iOiAiZ3B0LTRvLW1pbmki
|
||||
LCAiZGVsZWdhdGlvbl9lbmFibGVkPyI6IGZhbHNlLCAiYWxsb3dfY29kZV9leGVjdXRpb24/Ijog
|
||||
ZmFsc2UsICJtYXhfcmV0cnlfbGltaXQiOiAyLCAidG9vbHNfbmFtZXMiOiBbXX1dSvsBCgpjcmV3
|
||||
X3Rhc2tzEuwBCukBW3sia2V5IjogIjI3ZWYzOGNjOTlkYTRhOGRlZDcwZWQ0MDZlNDRhYjg2Iiwg
|
||||
ImlkIjogIjMzMDVhNTA5LTkyNWMtNGZlMS1hM2Y5LWQxZDJhZWRjMjA0OCIsICJhc3luY19leGVj
|
||||
dXRpb24/IjogZmFsc2UsICJodW1hbl9pbnB1dD8iOiBmYWxzZSwgImFnZW50X3JvbGUiOiAiU2Nv
|
||||
cmVyIiwgImFnZW50X2tleSI6ICI5MmU3ZWIxOTE2NjRjOTM1Nzg1ZWQ3ZDQyNDBhMjk0ZCIsICJ0
|
||||
b29sc19uYW1lcyI6IFtdfV16AhgBhQEAAQAAEo4CChCgvTrUWTdsLsGimQezpsavEggeGx9VfUy3
|
||||
XSoMVGFzayBDcmVhdGVkMAE5pKBm3iSjIhhBkHtn3iSjIhhKLgoIY3Jld19rZXkSIgogNWU2ZWZm
|
||||
ZTY4MGE1ZDk3ZGMzODczYjE0ODI1Y2NmYTNKMQoHY3Jld19pZBImCiRiZjg5ZmNlZC03ZmQwLTRj
|
||||
YmMtOTMxZi01NGU5ZmRkNGI3NWFKLgoIdGFza19rZXkSIgogMjdlZjM4Y2M5OWRhNGE4ZGVkNzBl
|
||||
ZDQwNmU0NGFiODZKMQoHdGFza19pZBImCiQzMzA1YTUwOS05MjVjLTRmZTEtYTNmOS1kMWQyYWVk
|
||||
YzIwNDh6AhgBhQEAAQAAEpsHChC2CvDRoXGax+N8/6eJx4iBEgjM4yG0OPuoJioMQ3JldyBDcmVh
|
||||
dGVkMAE5eL4B4CSjIhhBfXIQ4CSjIhhKGgoOY3Jld2FpX3ZlcnNpb24SCAoGMC44Ni4wShoKDnB5
|
||||
dGhvbl92ZXJzaW9uEggKBjMuMTIuN0ouCghjcmV3X2tleRIiCiA1ZTZlZmZlNjgwYTVkOTdkYzM4
|
||||
NzNiMTQ4MjVjY2ZhM0oxCgdjcmV3X2lkEiYKJDg1ODQ0MTA3LTc4YTMtNDk5Yy05ZmJlLWY5N2Q3
|
||||
YmUxNWMxMEocCgxjcmV3X3Byb2Nlc3MSDAoKc2VxdWVudGlhbEoRCgtjcmV3X21lbW9yeRICEABK
|
||||
GgoUY3Jld19udW1iZXJfb2ZfdGFza3MSAhgBShsKFWNyZXdfbnVtYmVyX29mX2FnZW50cxICGAFK
|
||||
zQIKC2NyZXdfYWdlbnRzEr0CCroCW3sia2V5IjogIjkyZTdlYjE5MTY2NGM5MzU3ODVlZDdkNDI0
|
||||
MGEyOTRkIiwgImlkIjogImVjYjI2MjQ4LWVlMjItNGY3Yy04NmY1LTlkNzExNjVkNjg4OSIsICJy
|
||||
b2xlIjogIlNjb3JlciIsICJ2ZXJib3NlPyI6IGZhbHNlLCAibWF4X2l0ZXIiOiAyMCwgIm1heF9y
|
||||
cG0iOiBudWxsLCAiZnVuY3Rpb25fY2FsbGluZ19sbG0iOiAiIiwgImxsbSI6ICJncHQtNG8tbWlu
|
||||
aSIsICJkZWxlZ2F0aW9uX2VuYWJsZWQ/IjogZmFsc2UsICJhbGxvd19jb2RlX2V4ZWN1dGlvbj8i
|
||||
OiBmYWxzZSwgIm1heF9yZXRyeV9saW1pdCI6IDIsICJ0b29sc19uYW1lcyI6IFtdfV1K+wEKCmNy
|
||||
ZXdfdGFza3MS7AEK6QFbeyJrZXkiOiAiMjdlZjM4Y2M5OWRhNGE4ZGVkNzBlZDQwNmU0NGFiODYi
|
||||
LCAiaWQiOiAiODlhMzUzMzMtNzA1My00MjBkLTkzMzgtOGMzYTUzYmVkMWFjIiwgImFzeW5jX2V4
|
||||
ZWN1dGlvbj8iOiBmYWxzZSwgImh1bWFuX2lucHV0PyI6IGZhbHNlLCAiYWdlbnRfcm9sZSI6ICJT
|
||||
Y29yZXIiLCAiYWdlbnRfa2V5IjogIjkyZTdlYjE5MTY2NGM5MzU3ODVlZDdkNDI0MGEyOTRkIiwg
|
||||
InRvb2xzX25hbWVzIjogW119XXoCGAGFAQABAAASjgIKEBCT8vlrSIuNdyhE+E+vrlsSCElG+Dpg
|
||||
qOQrKgxUYXNrIENyZWF0ZWQwATnblz/gJKMiGEEClEDgJKMiGEouCghjcmV3X2tleRIiCiA1ZTZl
|
||||
ZmZlNjgwYTVkOTdkYzM4NzNiMTQ4MjVjY2ZhM0oxCgdjcmV3X2lkEiYKJDg1ODQ0MTA3LTc4YTMt
|
||||
NDk5Yy05ZmJlLWY5N2Q3YmUxNWMxMEouCgh0YXNrX2tleRIiCiAyN2VmMzhjYzk5ZGE0YThkZWQ3
|
||||
MGVkNDA2ZTQ0YWI4NkoxCgd0YXNrX2lkEiYKJDg5YTM1MzMzLTcwNTMtNDIwZC05MzM4LThjM2E1
|
||||
M2JlZDFhY3oCGAGFAQABAAASmwcKEGfjx7vXoJroXfAT8kiUhs0SCMhz+zs7PpZXKgxDcmV3IENy
|
||||
ZWF0ZWQwATmBRtfhJKMiGEGOhObhJKMiGEoaCg5jcmV3YWlfdmVyc2lvbhIICgYwLjg2LjBKGgoO
|
||||
cHl0aG9uX3ZlcnNpb24SCAoGMy4xMi43Si4KCGNyZXdfa2V5EiIKIDVlNmVmZmU2ODBhNWQ5N2Rj
|
||||
Mzg3M2IxNDgyNWNjZmEzSjEKB2NyZXdfaWQSJgokZjRhNTZhNTgtYmEyZC00M2ZmLTkzNGUtMWU5
|
||||
NmZiYWViN2RlShwKDGNyZXdfcHJvY2VzcxIMCgpzZXF1ZW50aWFsShEKC2NyZXdfbWVtb3J5EgIQ
|
||||
AEoaChRjcmV3X251bWJlcl9vZl90YXNrcxICGAFKGwoVY3Jld19udW1iZXJfb2ZfYWdlbnRzEgIY
|
||||
AUrNAgoLY3Jld19hZ2VudHMSvQIKugJbeyJrZXkiOiAiOTJlN2ViMTkxNjY0YzkzNTc4NWVkN2Q0
|
||||
MjQwYTI5NGQiLCAiaWQiOiAiN2U1ZmE4MDgtNWY4MC00NGQ5LTk4OTEtY2YyNTU3NWI0MDVkIiwg
|
||||
InJvbGUiOiAiU2NvcmVyIiwgInZlcmJvc2U/IjogZmFsc2UsICJtYXhfaXRlciI6IDIwLCAibWF4
|
||||
X3JwbSI6IG51bGwsICJmdW5jdGlvbl9jYWxsaW5nX2xsbSI6ICIiLCAibGxtIjogImdwdC00by1t
|
||||
aW5pIiwgImRlbGVnYXRpb25fZW5hYmxlZD8iOiBmYWxzZSwgImFsbG93X2NvZGVfZXhlY3V0aW9u
|
||||
PyI6IGZhbHNlLCAibWF4X3JldHJ5X2xpbWl0IjogMiwgInRvb2xzX25hbWVzIjogW119XUr7AQoK
|
||||
Y3Jld190YXNrcxLsAQrpAVt7ImtleSI6ICIyN2VmMzhjYzk5ZGE0YThkZWQ3MGVkNDA2ZTQ0YWI4
|
||||
NiIsICJpZCI6ICJiYTMwMTk5Yi0wMmRkLTQxMTUtYTM1My0xZWRkMWU5YTMzNDgiLCAiYXN5bmNf
|
||||
ZXhlY3V0aW9uPyI6IGZhbHNlLCAiaHVtYW5faW5wdXQ/IjogZmFsc2UsICJhZ2VudF9yb2xlIjog
|
||||
IlNjb3JlciIsICJhZ2VudF9rZXkiOiAiOTJlN2ViMTkxNjY0YzkzNTc4NWVkN2Q0MjQwYTI5NGQi
|
||||
LCAidG9vbHNfbmFtZXMiOiBbXX1degIYAYUBAAEAABKOAgoQS3+R3parMKXuONFdpjtwFBIIvD72
|
||||
RJ4KtJcqDFRhc2sgQ3JlYXRlZDABOTVPCuIkoyIYQXYrC+IkoyIYSi4KCGNyZXdfa2V5EiIKIDVl
|
||||
NmVmZmU2ODBhNWQ5N2RjMzg3M2IxNDgyNWNjZmEzSjEKB2NyZXdfaWQSJgokZjRhNTZhNTgtYmEy
|
||||
ZC00M2ZmLTkzNGUtMWU5NmZiYWViN2RlSi4KCHRhc2tfa2V5EiIKIDI3ZWYzOGNjOTlkYTRhOGRl
|
||||
ZDcwZWQ0MDZlNDRhYjg2SjEKB3Rhc2tfaWQSJgokYmEzMDE5OWItMDJkZC00MTE1LWEzNTMtMWVk
|
||||
ZDFlOWEzMzQ4egIYAYUBAAEAABL9BgoQ0dT9mbr8GzJ/r4UmahrfShIIDk5xUvJSN5gqDENyZXcg
|
||||
Q3JlYXRlZDABOeW8HeMkoyIYQdVbLuMkoyIYShoKDmNyZXdhaV92ZXJzaW9uEggKBjAuODYuMEoa
|
||||
Cg5weXRob25fdmVyc2lvbhIICgYzLjEyLjdKLgoIY3Jld19rZXkSIgogNWU2ZWZmZTY4MGE1ZDk3
|
||||
ZGMzODczYjE0ODI1Y2NmYTNKMQoHY3Jld19pZBImCiQxMTIyZTk0MS1kZGRiLTQxMDMtODc3ZC01
|
||||
Zjk1ODFlOTQ2YjJKHgoMY3Jld19wcm9jZXNzEg4KDGhpZXJhcmNoaWNhbEoRCgtjcmV3X21lbW9y
|
||||
eRICEABKGgoUY3Jld19udW1iZXJfb2ZfdGFza3MSAhgBShsKFWNyZXdfbnVtYmVyX29mX2FnZW50
|
||||
cxICGAFKzQIKC2NyZXdfYWdlbnRzEr0CCroCW3sia2V5IjogIjkyZTdlYjE5MTY2NGM5MzU3ODVl
|
||||
ZDdkNDI0MGEyOTRkIiwgImlkIjogImJkOTViMTYzLTJjMTktNDk5NC04ZDdlLTg1ZWQ5Y2I4N2Q5
|
||||
OCIsICJyb2xlIjogIlNjb3JlciIsICJ2ZXJib3NlPyI6IGZhbHNlLCAibWF4X2l0ZXIiOiAyMCwg
|
||||
Im1heF9ycG0iOiBudWxsLCAiZnVuY3Rpb25fY2FsbGluZ19sbG0iOiAiIiwgImxsbSI6ICJncHQt
|
||||
NG8tbWluaSIsICJkZWxlZ2F0aW9uX2VuYWJsZWQ/IjogZmFsc2UsICJhbGxvd19jb2RlX2V4ZWN1
|
||||
dGlvbj8iOiBmYWxzZSwgIm1heF9yZXRyeV9saW1pdCI6IDIsICJ0b29sc19uYW1lcyI6IFtdfV1K
|
||||
2wEKCmNyZXdfdGFza3MSzAEKyQFbeyJrZXkiOiAiMjdlZjM4Y2M5OWRhNGE4ZGVkNzBlZDQwNmU0
|
||||
NGFiODYiLCAiaWQiOiAiZTA5NGNmZjMtMjFmNy00MmU3LTllYmMtMTdlZWU2NGQxZjFmIiwgImFz
|
||||
eW5jX2V4ZWN1dGlvbj8iOiBmYWxzZSwgImh1bWFuX2lucHV0PyI6IGZhbHNlLCAiYWdlbnRfcm9s
|
||||
ZSI6ICJOb25lIiwgImFnZW50X2tleSI6IG51bGwsICJ0b29sc19uYW1lcyI6IFtdfV16AhgBhQEA
|
||||
AQAAEo4CChDTux3x7AJX+9UYyMFiHzGyEghsGoTHBzkv5ioMVGFzayBDcmVhdGVkMAE5Ar9q4ySj
|
||||
IhhBYJRr4ySjIhhKLgoIY3Jld19rZXkSIgogNWU2ZWZmZTY4MGE1ZDk3ZGMzODczYjE0ODI1Y2Nm
|
||||
YTNKMQoHY3Jld19pZBImCiQxMTIyZTk0MS1kZGRiLTQxMDMtODc3ZC01Zjk1ODFlOTQ2YjJKLgoI
|
||||
dGFza19rZXkSIgogMjdlZjM4Y2M5OWRhNGE4ZGVkNzBlZDQwNmU0NGFiODZKMQoHdGFza19pZBIm
|
||||
CiRlMDk0Y2ZmMy0yMWY3LTQyZTctOWViYy0xN2VlZTY0ZDFmMWZ6AhgBhQEAAQAAEpsBChCJpDVw
|
||||
qjHKeZAX0+f3cMarEggJXNU1Xw0RHSoKVG9vbCBVc2FnZTABOZOPf+QkoyIYQTd5i+QkoyIYShoK
|
||||
DmNyZXdhaV92ZXJzaW9uEggKBjAuODYuMEonCgl0b29sX25hbWUSGgoYQXNrIHF1ZXN0aW9uIHRv
|
||||
IGNvd29ya2VySg4KCGF0dGVtcHRzEgIYAXoCGAGFAQABAAAS1QkKEPPNvumnQHJiFa9CWE78z2wS
|
||||
CKhH1yYXy4tIKgxDcmV3IENyZWF0ZWQwATmYG6blJKMiGEEF37XlJKMiGEoaCg5jcmV3YWlfdmVy
|
||||
c2lvbhIICgYwLjg2LjBKGgoOcHl0aG9uX3ZlcnNpb24SCAoGMy4xMi43Si4KCGNyZXdfa2V5EiIK
|
||||
IDc0Mjc1NzMxMmVmN2JiNGVlMGIwNjYyZDFjMmUyMTc5SjEKB2NyZXdfaWQSJgokOTU2NmQ0MDIt
|
||||
NTY4Yi00OTU0LWJiMWMtNWIxZmFhMDVlZTk5ShwKDGNyZXdfcHJvY2VzcxIMCgpzZXF1ZW50aWFs
|
||||
ShEKC2NyZXdfbWVtb3J5EgIQAEoaChRjcmV3X251bWJlcl9vZl90YXNrcxICGAFKGwoVY3Jld19u
|
||||
dW1iZXJfb2ZfYWdlbnRzEgIYAkqGBQoLY3Jld19hZ2VudHMS9gQK8wRbeyJrZXkiOiAiODljZjMx
|
||||
MWI0OGI1MjE2OWQ0MmYzOTI1YzViZTFjNWEiLCAiaWQiOiAiNzIwYjIxMDUtMzBhNS00YTc1LTgw
|
||||
OGYtNmM2NGUwZjQ2N2VhIiwgInJvbGUiOiAiTWFuYWdlciIsICJ2ZXJib3NlPyI6IGZhbHNlLCAi
|
||||
bWF4X2l0ZXIiOiAyMCwgIm1heF9ycG0iOiBudWxsLCAiZnVuY3Rpb25fY2FsbGluZ19sbG0iOiAi
|
||||
IiwgImxsbSI6ICJncHQtNG8tbWluaSIsICJkZWxlZ2F0aW9uX2VuYWJsZWQ/IjogdHJ1ZSwgImFs
|
||||
bG93X2NvZGVfZXhlY3V0aW9uPyI6IGZhbHNlLCAibWF4X3JldHJ5X2xpbWl0IjogMiwgInRvb2xz
|
||||
X25hbWVzIjogW119LCB7ImtleSI6ICI5MmU3ZWIxOTE2NjRjOTM1Nzg1ZWQ3ZDQyNDBhMjk0ZCIs
|
||||
ICJpZCI6ICJkMDBjZGZjOC1iZTQ5LTRhZGItOTg2NS1iYzM1N2FmMjA3MWQiLCAicm9sZSI6ICJT
|
||||
Y29yZXIiLCAidmVyYm9zZT8iOiBmYWxzZSwgIm1heF9pdGVyIjogMjAsICJtYXhfcnBtIjogbnVs
|
||||
bCwgImZ1bmN0aW9uX2NhbGxpbmdfbGxtIjogIiIsICJsbG0iOiAiZ3B0LTRvLW1pbmkiLCAiZGVs
|
||||
ZWdhdGlvbl9lbmFibGVkPyI6IHRydWUsICJhbGxvd19jb2RlX2V4ZWN1dGlvbj8iOiBmYWxzZSwg
|
||||
Im1heF9yZXRyeV9saW1pdCI6IDIsICJ0b29sc19uYW1lcyI6IFtdfV1K/AEKCmNyZXdfdGFza3MS
|
||||
7QEK6gFbeyJrZXkiOiAiMjdlZjM4Y2M5OWRhNGE4ZGVkNzBlZDQwNmU0NGFiODYiLCAiaWQiOiAi
|
||||
YTZhYWFhYzgtYTkyMC00YmVjLWI3ZWItODFmZWNiNzJhZDJhIiwgImFzeW5jX2V4ZWN1dGlvbj8i
|
||||
OiBmYWxzZSwgImh1bWFuX2lucHV0PyI6IGZhbHNlLCAiYWdlbnRfcm9sZSI6ICJNYW5hZ2VyIiwg
|
||||
ImFnZW50X2tleSI6ICI4OWNmMzExYjQ4YjUyMTY5ZDQyZjM5MjVjNWJlMWM1YSIsICJ0b29sc19u
|
||||
YW1lcyI6IFtdfV16AhgBhQEAAQAAEo4CChAzFyq3f1G5t8Y8mXBkDgQfEgj73hA6+iW3XSoMVGFz
|
||||
ayBDcmVhdGVkMAE5AE7o5SSjIhhBCSvp5SSjIhhKLgoIY3Jld19rZXkSIgogNzQyNzU3MzEyZWY3
|
||||
YmI0ZWUwYjA2NjJkMWMyZTIxNzlKMQoHY3Jld19pZBImCiQ5NTY2ZDQwMi01NjhiLTQ5NTQtYmIx
|
||||
Yy01YjFmYWEwNWVlOTlKLgoIdGFza19rZXkSIgogMjdlZjM4Y2M5OWRhNGE4ZGVkNzBlZDQwNmU0
|
||||
NGFiODZKMQoHdGFza19pZBImCiRhNmFhYWFjOC1hOTIwLTRiZWMtYjdlYi04MWZlY2I3MmFkMmF6
|
||||
AhgBhQEAAQAAEpwBChBu+7bw+lc2PWw8OQeYOPNJEgg2ErA4zogaWioKVG9vbCBVc2FnZTABOZM2
|
||||
+eYkoyIYQXKcBOckoyIYShoKDmNyZXdhaV92ZXJzaW9uEggKBjAuODYuMEooCgl0b29sX25hbWUS
|
||||
GwoZRGVsZWdhdGUgd29yayB0byBjb3dvcmtlckoOCghhdHRlbXB0cxICGAF6AhgBhQEAAQAAEo8H
|
||||
ChCFRpPRe+8nZTyXBduqSIWqEgj8M8rXzAHJsSoMQ3JldyBDcmVhdGVkMAE5UcA+6CSjIhhB7SxM
|
||||
6CSjIhhKGgoOY3Jld2FpX3ZlcnNpb24SCAoGMC44Ni4wShoKDnB5dGhvbl92ZXJzaW9uEggKBjMu
|
||||
MTIuN0ouCghjcmV3X2tleRIiCiAzMDNiOGVkZDViMDA4NzEwZDc2YWFmODI1YTcwOWU1NUoxCgdj
|
||||
cmV3X2lkEiYKJDliMmRiY2E2LTRhMzctNDEwMy1hM2YxLWIyN2NkNDFlYjgxNEoeCgxjcmV3X3By
|
||||
b2Nlc3MSDgoMaGllcmFyY2hpY2FsShEKC2NyZXdfbWVtb3J5EgIQAEoaChRjcmV3X251bWJlcl9v
|
||||
Zl90YXNrcxICGAFKGwoVY3Jld19udW1iZXJfb2ZfYWdlbnRzEgIYAUrfAgoLY3Jld19hZ2VudHMS
|
||||
zwIKzAJbeyJrZXkiOiAiOTJlN2ViMTkxNjY0YzkzNTc4NWVkN2Q0MjQwYTI5NGQiLCAiaWQiOiAi
|
||||
OGEzNzY0YTUtMDk1OC00ZGNlLWI5YjktYTg4NjNmNjM0ZGIxIiwgInJvbGUiOiAiU2NvcmVyIiwg
|
||||
InZlcmJvc2U/IjogZmFsc2UsICJtYXhfaXRlciI6IDIwLCAibWF4X3JwbSI6IG51bGwsICJmdW5j
|
||||
dGlvbl9jYWxsaW5nX2xsbSI6ICIiLCAibGxtIjogImdwdC00by1taW5pIiwgImRlbGVnYXRpb25f
|
||||
ZW5hYmxlZD8iOiBmYWxzZSwgImFsbG93X2NvZGVfZXhlY3V0aW9uPyI6IGZhbHNlLCAibWF4X3Jl
|
||||
dHJ5X2xpbWl0IjogMiwgInRvb2xzX25hbWVzIjogWyJzY29yaW5nX2V4YW1wbGVzIl19XUrbAQoK
|
||||
Y3Jld190YXNrcxLMAQrJAVt7ImtleSI6ICJmMzU3NWIwMTNjMjI5NGI3Y2M4ZTgwMzE1NWM4YmE0
|
||||
NiIsICJpZCI6ICJkODc2NmUwOS1hY2EyLTRjMWItYWUxMy1kMDg0Y2E1MmVmY2EiLCAiYXN5bmNf
|
||||
ZXhlY3V0aW9uPyI6IGZhbHNlLCAiaHVtYW5faW5wdXQ/IjogZmFsc2UsICJhZ2VudF9yb2xlIjog
|
||||
Ik5vbmUiLCAiYWdlbnRfa2V5IjogbnVsbCwgInRvb2xzX25hbWVzIjogW119XXoCGAGFAQABAAAS
|
||||
jgIKEKc2mouS/G0bxR5cvUwFjLMSCPEWt/7342YfKgxUYXNrIENyZWF0ZWQwATlo74roJKMiGEGu
|
||||
OI3oJKMiGEouCghjcmV3X2tleRIiCiAzMDNiOGVkZDViMDA4NzEwZDc2YWFmODI1YTcwOWU1NUox
|
||||
CgdjcmV3X2lkEiYKJDliMmRiY2E2LTRhMzctNDEwMy1hM2YxLWIyN2NkNDFlYjgxNEouCgh0YXNr
|
||||
X2tleRIiCiBmMzU3NWIwMTNjMjI5NGI3Y2M4ZTgwMzE1NWM4YmE0NkoxCgd0YXNrX2lkEiYKJGQ4
|
||||
NzY2ZTA5LWFjYTItNGMxYi1hZTEzLWQwODRjYTUyZWZjYXoCGAGFAQABAAASaAoQPF7lk/Hx6/o9
|
||||
Gjt/NdMYORIIkj7Pmjc21HAqEFRvb2wgVXNhZ2UgRXJyb3IwATmxdqbpJKMiGEHR0rHpJKMiGEoa
|
||||
Cg5jcmV3YWlfdmVyc2lvbhIICgYwLjg2LjB6AhgBhQEAAQAAEpwBChBXI0xbMpaE75suG3xa+bAM
|
||||
EgjYJb0HxD9kAyoKVG9vbCBVc2FnZTABOeatXuskoyIYQZGea+skoyIYShoKDmNyZXdhaV92ZXJz
|
||||
aW9uEggKBjAuODYuMEooCgl0b29sX25hbWUSGwoZRGVsZWdhdGUgd29yayB0byBjb3dvcmtlckoO
|
||||
CghhdHRlbXB0cxICGAF6AhgBhQEAAQAA
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Length:
|
||||
- '27954'
|
||||
Content-Type:
|
||||
- application/x-protobuf
|
||||
User-Agent:
|
||||
- OTel-OTLP-Exporter-Python/1.27.0
|
||||
method: POST
|
||||
uri: https://telemetry.crewai.com:4319/v1/traces
|
||||
response:
|
||||
body:
|
||||
string: "\n\0"
|
||||
headers:
|
||||
Content-Length:
|
||||
- '2'
|
||||
Content-Type:
|
||||
- application/x-protobuf
|
||||
Date:
|
||||
- Sun, 09 Feb 2025 20:09:48 GMT
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
- request:
|
||||
body: '{"messages": [{"role": "system", "content": "You are Research Manager.
|
||||
You''re a research expert\nYour personal goal is: Manage research\nTo give my
|
||||
best complete final answer to the task use the exact following format:\n\nThought:
|
||||
I now can give a great answer\nFinal Answer: Your final answer must be the great
|
||||
and the most complete as possible, it must be outcome described.\n\nI MUST use
|
||||
these formats, my job depends on it!"}, {"role": "user", "content": "\nCurrent
|
||||
Task: Handle research\n\nThis is the expect criteria for your final answer:
|
||||
Your best answer to your coworker asking you this, accounting for the context
|
||||
shared.\nyou MUST return the actual complete content as the final answer, not
|
||||
a summary.\n\nThis is the context you''re working with:\nImportant research\n\nBegin!
|
||||
This is VERY important to you, use the tools available and give your best Final
|
||||
Answer, your job depends on it!\n\nThought:"}], "model": "gpt-4o-mini", "stop":
|
||||
["\nObservation:"], "stream": false}'
|
||||
headers:
|
||||
accept:
|
||||
- application/json
|
||||
accept-encoding:
|
||||
- gzip, deflate
|
||||
connection:
|
||||
- keep-alive
|
||||
content-length:
|
||||
- '983'
|
||||
content-type:
|
||||
- application/json
|
||||
cookie:
|
||||
- _cfuvid=FasG_74jjKfEtA2Mjn2iKdu62tv3zosBxYNYTk1E12M-1734025911900-0.0.1.1-604800000
|
||||
host:
|
||||
- api.openai.com
|
||||
user-agent:
|
||||
- OpenAI/Python 1.52.1
|
||||
x-stainless-arch:
|
||||
- x64
|
||||
x-stainless-async:
|
||||
- 'false'
|
||||
x-stainless-lang:
|
||||
- python
|
||||
x-stainless-os:
|
||||
- Linux
|
||||
x-stainless-package-version:
|
||||
- 1.52.1
|
||||
x-stainless-raw-response:
|
||||
- 'true'
|
||||
x-stainless-retry-count:
|
||||
- '0'
|
||||
x-stainless-runtime:
|
||||
- CPython
|
||||
x-stainless-runtime-version:
|
||||
- 3.12.7
|
||||
method: POST
|
||||
uri: https://api.openai.com/v1/chat/completions
|
||||
response:
|
||||
content: "{\n \"id\": \"chatcmpl-Az7ubIqhsC9H8pB1PRAOfDeSE2ViF\",\n \"object\":
|
||||
\"chat.completion\",\n \"created\": 1739131785,\n \"model\": \"gpt-4o-mini-2024-07-18\",\n
|
||||
\ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\":
|
||||
\"assistant\",\n \"content\": \"I now can give a great answer \\nFinal
|
||||
Answer: Given the critical importance of this research, we must ensure that
|
||||
our approach is thorough and systematic. Here\u2019s a detailed plan that outlines
|
||||
the key steps for handling this research effectively:\\n\\n1. **Define Research
|
||||
Objectives**: Clearly articulate what we aim to achieve with this research.
|
||||
This should include specific questions we want to answer and the impact this
|
||||
information will have on our current projects.\\n\\n2. **Gather Relevant Data**:
|
||||
Identify and collect data related to our research objectives. This may involve
|
||||
both primary and secondary data sources. Ensure that the data is credible, relevant,
|
||||
and up-to-date to maintain the integrity of our research findings.\\n\\n3. **Conduct
|
||||
Literature Review**: Review existing literature on the topic to understand previous
|
||||
research findings and methodologies. This will help us identify gaps in the
|
||||
existing research and position our study effectively.\\n\\n4. **Select Research
|
||||
Methodology**: Decide on appropriate research methods (qualitative, quantitative,
|
||||
or mixed methods) based on our objectives and the type of data we have gathered.
|
||||
This may include surveys, interviews, or data analysis techniques.\\n\\n5. **Pilot
|
||||
Study**: If necessary, conduct a pilot study to test our research methods and
|
||||
refine our approach. This will help identify any potential issues in our research
|
||||
design.\\n\\n6. **Data Analysis**: Once data is collected, analyze it systematically.
|
||||
Depending on the nature of the data, this may involve various statistical techniques,
|
||||
thematic analysis, or software solutions to derive insights.\\n\\n7. **Interpret
|
||||
Results**: Draw conclusions from our analysis. How do the findings relate to
|
||||
our initial research questions? What implications do these results have for
|
||||
our projects and wider context?\\n\\n8. **Documentation and Reporting**: Compile
|
||||
our findings into a structured report that includes an introduction, methodology,
|
||||
results, discussion, and conclusion. Make sure to follow any formatting or submission
|
||||
guidelines provided.\\n\\n9. **Feedback and Revision**: Share the draft report
|
||||
with stakeholders for feedback. Be open to critiques and make the necessary
|
||||
revisions to enhance the quality and accuracy of our research.\\n\\n10. **Presentation
|
||||
and Dissemination**: Prepare a presentation to communicate our findings to relevant
|
||||
teams or stakeholders. Highlight key insights and recommendations based on our
|
||||
research.\\n\\n11. **Follow Up**: After disseminating the results, plan for
|
||||
any follow-up actions or further research that might be required based on the
|
||||
insights gained.\\n\\nBy following this comprehensive research strategy, we
|
||||
can ensure that the handling of this important research project is managed effectively
|
||||
and leads to impactful outcomes for our organization.\",\n \"refusal\":
|
||||
null\n },\n \"logprobs\": null,\n \"finish_reason\": \"stop\"\n
|
||||
\ }\n ],\n \"usage\": {\n \"prompt_tokens\": 179,\n \"completion_tokens\":
|
||||
508,\n \"total_tokens\": 687,\n \"prompt_tokens_details\": {\n \"cached_tokens\":
|
||||
0,\n \"audio_tokens\": 0\n },\n \"completion_tokens_details\": {\n
|
||||
\ \"reasoning_tokens\": 0,\n \"audio_tokens\": 0,\n \"accepted_prediction_tokens\":
|
||||
0,\n \"rejected_prediction_tokens\": 0\n }\n },\n \"service_tier\":
|
||||
\"default\",\n \"system_fingerprint\": \"fp_72ed7ab54c\"\n}\n"
|
||||
headers:
|
||||
CF-RAY:
|
||||
- 90f67fbb7f7b76f1-SEA
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Encoding:
|
||||
- gzip
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Sun, 09 Feb 2025 20:10:02 GMT
|
||||
Server:
|
||||
- cloudflare
|
||||
Set-Cookie:
|
||||
- __cf_bm=UYR3lic9ZX3q_w8ul5YU1NoMKLvuFEK8LNu_O.5QPcU-1739131802-1.0.1.1-K5kQYiuLVp2wZpT4pe1oC.zjo4mBzVzXvfIChY.A419uN54s97KQRauV2PBI5ArtsbDEMIaVV3GOZaAtCfAClg;
|
||||
path=/; expires=Sun, 09-Feb-25 20:40:02 GMT; domain=.api.openai.com; HttpOnly;
|
||||
Secure; SameSite=None
|
||||
- _cfuvid=GxztReZeGi6qENS0TkwOuBgjGx3aFWu5H5e9HnTkQRI-1739131802782-0.0.1.1-604800000;
|
||||
path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
access-control-expose-headers:
|
||||
- X-Request-ID
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
cf-cache-status:
|
||||
- DYNAMIC
|
||||
openai-organization:
|
||||
- crewai-iuxna1
|
||||
openai-processing-ms:
|
||||
- '17157'
|
||||
openai-version:
|
||||
- '2020-10-01'
|
||||
strict-transport-security:
|
||||
- max-age=31536000; includeSubDomains; preload
|
||||
x-ratelimit-limit-requests:
|
||||
- '30000'
|
||||
x-ratelimit-limit-tokens:
|
||||
- '150000000'
|
||||
x-ratelimit-remaining-requests:
|
||||
- '29999'
|
||||
x-ratelimit-remaining-tokens:
|
||||
- '149999777'
|
||||
x-ratelimit-reset-requests:
|
||||
- 2ms
|
||||
x-ratelimit-reset-tokens:
|
||||
- 0s
|
||||
x-request-id:
|
||||
- req_069685adeeddff8992b6b2cbb5ba8514
|
||||
http_version: HTTP/1.1
|
||||
status_code: 200
|
||||
version: 1
|
||||
68
uv.lock
generated
68
uv.lock
generated
@@ -1,18 +1,10 @@
|
||||
version = 1
|
||||
requires-python = ">=3.10, <3.13"
|
||||
resolution-markers = [
|
||||
"python_full_version < '3.11' and sys_platform == 'darwin'",
|
||||
"python_full_version < '3.11' and platform_machine == 'aarch64' and sys_platform == 'linux'",
|
||||
"(python_full_version < '3.11' and platform_machine != 'aarch64' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform != 'darwin' and sys_platform != 'linux')",
|
||||
"python_full_version == '3.11.*' and sys_platform == 'darwin'",
|
||||
"python_full_version == '3.11.*' and platform_machine == 'aarch64' and sys_platform == 'linux'",
|
||||
"(python_full_version == '3.11.*' and platform_machine != 'aarch64' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform != 'darwin' and sys_platform != 'linux')",
|
||||
"python_full_version >= '3.12' and python_full_version < '3.12.4' and sys_platform == 'darwin'",
|
||||
"python_full_version >= '3.12' and python_full_version < '3.12.4' and platform_machine == 'aarch64' and sys_platform == 'linux'",
|
||||
"(python_full_version >= '3.12' and python_full_version < '3.12.4' and platform_machine != 'aarch64' and sys_platform == 'linux') or (python_full_version >= '3.12' and python_full_version < '3.12.4' and sys_platform != 'darwin' and sys_platform != 'linux')",
|
||||
"python_full_version >= '3.12.4' and sys_platform == 'darwin'",
|
||||
"python_full_version >= '3.12.4' and platform_machine == 'aarch64' and sys_platform == 'linux'",
|
||||
"(python_full_version >= '3.12.4' and platform_machine != 'aarch64' and sys_platform == 'linux') or (python_full_version >= '3.12.4' and sys_platform != 'darwin' and sys_platform != 'linux')",
|
||||
"python_full_version < '3.11'",
|
||||
"python_full_version == '3.11.*'",
|
||||
"python_full_version >= '3.12' and python_full_version < '3.12.4'",
|
||||
"python_full_version >= '3.12.4'",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -308,7 +300,7 @@ name = "build"
|
||||
version = "1.2.2.post1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "colorama", marker = "(os_name == 'nt' and platform_machine != 'aarch64' and sys_platform == 'linux') or (os_name == 'nt' and sys_platform != 'darwin' and sys_platform != 'linux')" },
|
||||
{ name = "colorama", marker = "os_name == 'nt'" },
|
||||
{ name = "importlib-metadata", marker = "python_full_version < '3.10.2'" },
|
||||
{ name = "packaging" },
|
||||
{ name = "pyproject-hooks" },
|
||||
@@ -543,7 +535,7 @@ name = "click"
|
||||
version = "8.1.7"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||
{ name = "colorama", marker = "platform_system == 'Windows'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/96/d3/f04c7bfcf5c1862a2a5b845c6b2b360488cf47af55dfa79c98f6a6bf98b5/click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de", size = 336121 }
|
||||
wheels = [
|
||||
@@ -650,6 +642,7 @@ tools = [
|
||||
[package.dev-dependencies]
|
||||
dev = [
|
||||
{ name = "cairosvg" },
|
||||
{ name = "crewai-tools" },
|
||||
{ name = "mkdocs" },
|
||||
{ name = "mkdocs-material" },
|
||||
{ name = "mkdocs-material-extensions" },
|
||||
@@ -703,6 +696,7 @@ requires-dist = [
|
||||
[package.metadata.requires-dev]
|
||||
dev = [
|
||||
{ name = "cairosvg", specifier = ">=2.7.1" },
|
||||
{ name = "crewai-tools", specifier = ">=0.17.0" },
|
||||
{ name = "mkdocs", specifier = ">=1.4.3" },
|
||||
{ name = "mkdocs-material", specifier = ">=9.5.7" },
|
||||
{ name = "mkdocs-material-extensions", specifier = ">=1.3.1" },
|
||||
@@ -2468,7 +2462,7 @@ version = "1.6.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "click" },
|
||||
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||
{ name = "colorama", marker = "platform_system == 'Windows'" },
|
||||
{ name = "ghp-import" },
|
||||
{ name = "jinja2" },
|
||||
{ name = "markdown" },
|
||||
@@ -2649,7 +2643,7 @@ version = "2.10.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "pygments" },
|
||||
{ name = "pywin32", marker = "sys_platform == 'win32'" },
|
||||
{ name = "pywin32", marker = "platform_system == 'Windows'" },
|
||||
{ name = "tqdm" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/3a/93/80ac75c20ce54c785648b4ed363c88f148bf22637e10c9863db4fbe73e74/mpire-2.10.2.tar.gz", hash = "sha256:f66a321e93fadff34585a4bfa05e95bd946cf714b442f51c529038eb45773d97", size = 271270 }
|
||||
@@ -2896,7 +2890,7 @@ name = "nvidia-cudnn-cu12"
|
||||
version = "9.1.0.70"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "nvidia-cublas-cu12", marker = "(platform_machine != 'aarch64' and sys_platform == 'linux') or (sys_platform != 'darwin' and sys_platform != 'linux')" },
|
||||
{ name = "nvidia-cublas-cu12", marker = "(platform_machine != 'aarch64' and platform_system != 'Darwin') or (platform_system != 'Darwin' and platform_system != 'Linux')" },
|
||||
]
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/9f/fd/713452cd72343f682b1c7b9321e23829f00b842ceaedcda96e742ea0b0b3/nvidia_cudnn_cu12-9.1.0.70-py3-none-manylinux2014_x86_64.whl", hash = "sha256:165764f44ef8c61fcdfdfdbe769d687e06374059fbb388b6c89ecb0e28793a6f", size = 664752741 },
|
||||
@@ -2923,9 +2917,9 @@ name = "nvidia-cusolver-cu12"
|
||||
version = "11.4.5.107"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "nvidia-cublas-cu12", marker = "(platform_machine != 'aarch64' and sys_platform == 'linux') or (sys_platform != 'darwin' and sys_platform != 'linux')" },
|
||||
{ name = "nvidia-cusparse-cu12", marker = "(platform_machine != 'aarch64' and sys_platform == 'linux') or (sys_platform != 'darwin' and sys_platform != 'linux')" },
|
||||
{ name = "nvidia-nvjitlink-cu12", marker = "(platform_machine != 'aarch64' and sys_platform == 'linux') or (sys_platform != 'darwin' and sys_platform != 'linux')" },
|
||||
{ name = "nvidia-cublas-cu12", marker = "(platform_machine != 'aarch64' and platform_system != 'Darwin') or (platform_system != 'Darwin' and platform_system != 'Linux')" },
|
||||
{ name = "nvidia-cusparse-cu12", marker = "(platform_machine != 'aarch64' and platform_system != 'Darwin') or (platform_system != 'Darwin' and platform_system != 'Linux')" },
|
||||
{ name = "nvidia-nvjitlink-cu12", marker = "(platform_machine != 'aarch64' and platform_system != 'Darwin') or (platform_system != 'Darwin' and platform_system != 'Linux')" },
|
||||
]
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/bc/1d/8de1e5c67099015c834315e333911273a8c6aaba78923dd1d1e25fc5f217/nvidia_cusolver_cu12-11.4.5.107-py3-none-manylinux1_x86_64.whl", hash = "sha256:8a7ec542f0412294b15072fa7dab71d31334014a69f953004ea7a118206fe0dd", size = 124161928 },
|
||||
@@ -2936,7 +2930,7 @@ name = "nvidia-cusparse-cu12"
|
||||
version = "12.1.0.106"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "nvidia-nvjitlink-cu12", marker = "(platform_machine != 'aarch64' and sys_platform == 'linux') or (sys_platform != 'darwin' and sys_platform != 'linux')" },
|
||||
{ name = "nvidia-nvjitlink-cu12", marker = "(platform_machine != 'aarch64' and platform_system != 'Darwin') or (platform_system != 'Darwin' and platform_system != 'Linux')" },
|
||||
]
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/65/5b/cfaeebf25cd9fdec14338ccb16f6b2c4c7fa9163aefcf057d86b9cc248bb/nvidia_cusparse_cu12-12.1.0.106-py3-none-manylinux1_x86_64.whl", hash = "sha256:f3b50f42cf363f86ab21f720998517a659a48131e8d538dc02f8768237bd884c", size = 195958278 },
|
||||
@@ -3486,7 +3480,7 @@ name = "portalocker"
|
||||
version = "2.10.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "pywin32", marker = "sys_platform == 'win32'" },
|
||||
{ name = "pywin32", marker = "platform_system == 'Windows'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ed/d3/c6c64067759e87af98cc668c1cc75171347d0f1577fab7ca3749134e3cd4/portalocker-2.10.1.tar.gz", hash = "sha256:ef1bf844e878ab08aee7e40184156e1151f228f103aa5c6bd0724cc330960f8f", size = 40891 }
|
||||
wheels = [
|
||||
@@ -5028,19 +5022,19 @@ dependencies = [
|
||||
{ name = "fsspec" },
|
||||
{ name = "jinja2" },
|
||||
{ name = "networkx" },
|
||||
{ name = "nvidia-cublas-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
|
||||
{ name = "nvidia-cuda-cupti-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
|
||||
{ name = "nvidia-cuda-nvrtc-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
|
||||
{ name = "nvidia-cuda-runtime-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
|
||||
{ name = "nvidia-cudnn-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
|
||||
{ name = "nvidia-cufft-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
|
||||
{ name = "nvidia-curand-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
|
||||
{ name = "nvidia-cusolver-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
|
||||
{ name = "nvidia-cusparse-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
|
||||
{ name = "nvidia-nccl-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
|
||||
{ name = "nvidia-nvtx-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
|
||||
{ name = "nvidia-cublas-cu12", marker = "platform_machine == 'x86_64' and platform_system == 'Linux'" },
|
||||
{ name = "nvidia-cuda-cupti-cu12", marker = "platform_machine == 'x86_64' and platform_system == 'Linux'" },
|
||||
{ name = "nvidia-cuda-nvrtc-cu12", marker = "platform_machine == 'x86_64' and platform_system == 'Linux'" },
|
||||
{ name = "nvidia-cuda-runtime-cu12", marker = "platform_machine == 'x86_64' and platform_system == 'Linux'" },
|
||||
{ name = "nvidia-cudnn-cu12", marker = "platform_machine == 'x86_64' and platform_system == 'Linux'" },
|
||||
{ name = "nvidia-cufft-cu12", marker = "platform_machine == 'x86_64' and platform_system == 'Linux'" },
|
||||
{ name = "nvidia-curand-cu12", marker = "platform_machine == 'x86_64' and platform_system == 'Linux'" },
|
||||
{ name = "nvidia-cusolver-cu12", marker = "platform_machine == 'x86_64' and platform_system == 'Linux'" },
|
||||
{ name = "nvidia-cusparse-cu12", marker = "platform_machine == 'x86_64' and platform_system == 'Linux'" },
|
||||
{ name = "nvidia-nccl-cu12", marker = "platform_machine == 'x86_64' and platform_system == 'Linux'" },
|
||||
{ name = "nvidia-nvtx-cu12", marker = "platform_machine == 'x86_64' and platform_system == 'Linux'" },
|
||||
{ name = "sympy" },
|
||||
{ name = "triton", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
|
||||
{ name = "triton", marker = "platform_machine == 'x86_64' and platform_system == 'Linux'" },
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
wheels = [
|
||||
@@ -5087,7 +5081,7 @@ name = "tqdm"
|
||||
version = "4.66.5"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||
{ name = "colorama", marker = "platform_system == 'Windows'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/58/83/6ba9844a41128c62e810fddddd72473201f3eacde02046066142a2d96cc5/tqdm-4.66.5.tar.gz", hash = "sha256:e1020aef2e5096702d8a025ac7d16b1577279c9d63f8375b63083e9a5f0fcbad", size = 169504 }
|
||||
wheels = [
|
||||
@@ -5130,7 +5124,7 @@ version = "0.27.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "attrs" },
|
||||
{ name = "cffi", marker = "(implementation_name != 'pypy' and os_name == 'nt' and platform_machine != 'aarch64' and sys_platform == 'linux') or (implementation_name != 'pypy' and os_name == 'nt' and sys_platform != 'darwin' and sys_platform != 'linux')" },
|
||||
{ name = "cffi", marker = "implementation_name != 'pypy' and os_name == 'nt'" },
|
||||
{ name = "exceptiongroup", marker = "python_full_version < '3.11'" },
|
||||
{ name = "idna" },
|
||||
{ name = "outcome" },
|
||||
@@ -5161,7 +5155,7 @@ name = "triton"
|
||||
version = "3.0.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "filelock", marker = "(platform_machine != 'aarch64' and sys_platform == 'linux') or (sys_platform != 'darwin' and sys_platform != 'linux')" },
|
||||
{ name = "filelock", marker = "(platform_machine != 'aarch64' and platform_system != 'Darwin') or (platform_system != 'Darwin' and platform_system != 'Linux')" },
|
||||
]
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/45/27/14cc3101409b9b4b9241d2ba7deaa93535a217a211c86c4cc7151fb12181/triton-3.0.0-1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e1efef76935b2febc365bfadf74bcb65a6f959a9872e5bddf44cc9e0adce1e1a", size = 209376304 },
|
||||
|
||||
Reference in New Issue
Block a user