Skip to content

Commit 05b124d

Browse files
Copilotg3force
andcommitted
Fix Makefile tabs and ruff import order after pre-commit hooks
Co-authored-by: g3force <779094+g3force@users.noreply.github.com>
1 parent 9fb70b3 commit 05b124d

File tree

16 files changed

+2150
-429
lines changed

16 files changed

+2150
-429
lines changed

Makefile

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,29 @@ all: build
55
.PHONY: build
66
build:
77
uv sync --all-packages
8+
cd msaf && uv sync
89

910

1011
.PHONY: test
1112
test: build
1213
uv run pytest
14+
cd msaf && uv run pytest
1315

1416

1517
.PHONY: check
1618
check: build
1719
uv run ruff check
1820
uv run mypy .
1921
uv run bandit -c pyproject.toml -r .
22+
cd msaf && uv run ruff check
23+
cd msaf && uv run mypy .
24+
cd msaf && uv run bandit -c pyproject.toml -r .
2025
make test
2126

2227

2328
.PHONY: check-fix
2429
check-fix: build
2530
uv run ruff format
2631
uv run ruff check --fix
32+
cd msaf && uv run ruff format
33+
cd msaf && uv run ruff check --fix

adk/agenticlayer/agent.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
import httpx
99
from a2a.client import A2ACardResolver
1010
from a2a.utils.constants import AGENT_CARD_WELL_KNOWN_PATH
11+
from agenticlayer_shared.config import InteractionType, McpTool, SubAgent
12+
from agenticlayer_shared.constants import HTTP_HEADERS_SESSION_KEY
1113
from google.adk.agents import BaseAgent, LlmAgent
1214
from google.adk.agents.llm_agent import ToolUnion
1315
from google.adk.agents.readonly_context import ReadonlyContext
@@ -17,9 +19,6 @@
1719
from google.adk.tools.mcp_tool.mcp_toolset import McpToolset
1820
from httpx_retries import Retry, RetryTransport
1921

20-
from agenticlayer.config import InteractionType, McpTool, SubAgent
21-
from agenticlayer.constants import HTTP_HEADERS_SESSION_KEY
22-
2322
logger = logging.getLogger(__name__)
2423

2524

adk/agenticlayer/agent_to_a2a.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
from a2a.server.tasks import InMemoryTaskStore
1414
from a2a.types import AgentCapabilities, AgentCard
1515
from a2a.utils.constants import AGENT_CARD_WELL_KNOWN_PATH
16+
from agenticlayer_shared.config import McpTool, SubAgent
17+
from agenticlayer_shared.constants import HTTP_HEADERS_SESSION_KEY
1618
from google.adk.a2a.converters.request_converter import AgentRunRequest
1719
from google.adk.a2a.executor.a2a_agent_executor import A2aAgentExecutor
1820
from google.adk.agents import LlmAgent
@@ -30,8 +32,6 @@
3032

3133
from .agent import AgentFactory
3234
from .callback_tracer_plugin import CallbackTracerPlugin
33-
from .config import McpTool, SubAgent
34-
from .constants import HTTP_HEADERS_SESSION_KEY
3535
from .metrics_plugin import MetricsPlugin
3636

3737
logger = logging.getLogger(__name__)
@@ -224,7 +224,7 @@ async def lifespan(app: Starlette) -> AsyncIterator[None]:
224224
starlette_app = Starlette(lifespan=lifespan)
225225

226226
# Instrument the Starlette app with OpenTelemetry
227-
from .otel_starlette import instrument_starlette_app
227+
from agenticlayer_shared.otel_starlette import instrument_starlette_app
228228

229229
instrument_starlette_app(starlette_app)
230230

adk/agenticlayer/config.py

Lines changed: 3 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,8 @@
11
"""
22
Configuration parsing for sub-agents and tools.
3-
Parses JSON configurations to create RemoteA2aAgents, AgentTools and McpToolsets.
3+
Re-exported from agenticlayer_shared for backward compatibility.
44
"""
55

6-
import json
7-
from enum import Enum
6+
from agenticlayer_shared.config import InteractionType, McpTool, SubAgent, parse_sub_agents, parse_tools
87

9-
from pydantic import AnyHttpUrl, BaseModel
10-
11-
12-
class InteractionType(str, Enum):
13-
TOOL_CALL = "tool_call"
14-
TRANSFER = "transfer"
15-
16-
17-
class SubAgent(BaseModel):
18-
name: str
19-
url: AnyHttpUrl
20-
interaction_type: InteractionType = InteractionType.TOOL_CALL
21-
22-
23-
class McpTool(BaseModel):
24-
name: str
25-
url: AnyHttpUrl
26-
timeout: int = 30
27-
propagate_headers: list[str] = []
28-
29-
30-
def parse_sub_agents(sub_agents_config: str) -> list[SubAgent]:
31-
"""
32-
Get sub agents from JSON string.
33-
Format: {"agent_name": {"url": "http://agent_url", "interaction_type", "transfer|tool_call"}, ...}
34-
35-
:return: A tuple of:
36-
- list of sub agents for transfer interaction type
37-
- list of agent tools for tool_call interaction type
38-
"""
39-
40-
try:
41-
agents_map = json.loads(sub_agents_config)
42-
except json.JSONDecodeError as e:
43-
raise ValueError("Warning: Invalid JSON in SUB_AGENTS environment variable: " + sub_agents_config, e)
44-
45-
return [
46-
SubAgent(
47-
name=agent_name,
48-
url=config["url"],
49-
interaction_type=InteractionType(config.get("interaction_type", "tool_call")),
50-
)
51-
for agent_name, config in agents_map.items()
52-
]
53-
54-
55-
def parse_tools(tools_config: str) -> list[McpTool]:
56-
"""
57-
Get tools from JSON string.
58-
Format: {"tool_name": {"url": "http://tool_url", "timeout": 30}, ...}
59-
60-
:return: A list of McpToolset tools
61-
"""
62-
63-
try:
64-
tools_map = json.loads(tools_config)
65-
except json.JSONDecodeError as e:
66-
raise ValueError("Warning: Invalid JSON in AGENT_TOOLS environment variable: " + tools_config, e)
67-
68-
return [
69-
McpTool(
70-
name=name,
71-
url=config["url"],
72-
timeout=config.get("timeout", 30),
73-
)
74-
for name, config in tools_map.items()
75-
]
8+
__all__ = ["InteractionType", "McpTool", "SubAgent", "parse_sub_agents", "parse_tools"]

adk/agenticlayer/constants.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
"""Constants shared across the agenticlayer package."""
1+
"""Constants shared across the agenticlayer package.
2+
Re-exported from agenticlayer_shared for backward compatibility.
3+
"""
24

3-
# Prefix used to store propagated HTTP headers in ADK session state as flat primitive keys.
4-
# Each header is stored as a separate string entry: f"{HTTP_HEADERS_SESSION_KEY}.{header_name_lower}"
5-
# e.g. "http_headers.authorization" -> "Bearer token"
6-
HTTP_HEADERS_SESSION_KEY = "http_headers"
5+
from agenticlayer_shared.constants import HTTP_HEADERS_SESSION_KEY
6+
7+
__all__ = ["HTTP_HEADERS_SESSION_KEY"]

adk/agenticlayer/loguru_config.py

Lines changed: 5 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -1,131 +1,7 @@
1-
from __future__ import annotations
1+
"""Loguru configuration.
2+
Re-exported from agenticlayer_shared for backward compatibility.
3+
"""
24

3-
import inspect
4-
import json
5-
import logging
6-
import os
7-
import sys
8-
import traceback
9-
from logging import Logger
10-
from typing import Callable, NotRequired, TextIO, TypedDict, Union
5+
from agenticlayer_shared.loguru_config import InterceptHandler, setup_logging
116

12-
import loguru
13-
from loguru import logger
14-
15-
16-
class JsonRecord(TypedDict):
17-
timestamp: str
18-
name: str | None
19-
level: str
20-
message: str
21-
function: str
22-
module: str
23-
line: int
24-
exception: NotRequired[dict[str, str]]
25-
26-
27-
def _serialize(record: loguru.Record) -> str:
28-
log: JsonRecord = {
29-
"timestamp": record["time"].isoformat(),
30-
"name": record["name"],
31-
"level": record["level"].name,
32-
"message": record["message"],
33-
"function": record["function"],
34-
"module": record["module"],
35-
"line": record["line"],
36-
}
37-
38-
if record["exception"] is not None:
39-
log["exception"] = {
40-
"stack": "".join(
41-
traceback.format_exception(
42-
record["exception"].type,
43-
record["exception"].value,
44-
record["exception"].traceback,
45-
)
46-
),
47-
"kind": getattr(record["exception"].type, "__name__", "None"),
48-
"message": str(record["exception"].value),
49-
}
50-
51-
return json.dumps(log)
52-
53-
54-
def _json_sink(message: loguru.Message) -> None:
55-
serialized = _serialize(message.record)
56-
sys.stderr.write(serialized + "\n")
57-
58-
59-
def _configure_loguru() -> None:
60-
sink: Union[TextIO, Callable[[loguru.Message], None]]
61-
log_format = os.environ.get("LOG_FORMAT", "Text")
62-
if log_format == "JSON":
63-
sink = _json_sink
64-
else:
65-
sink = sys.stderr
66-
67-
log_level = os.environ.get("LOGLEVEL", "INFO")
68-
69-
logger.remove()
70-
logger.add(
71-
sink,
72-
# Log INFO by default
73-
filter={
74-
"": log_level,
75-
# Reduce verbosity of some noisy loggers
76-
"a2a.utils.telemetry": "INFO",
77-
},
78-
)
79-
80-
81-
def setup_logging() -> None:
82-
"""Initializes the application so that logging is handled by loguru"""
83-
84-
_configure_loguru()
85-
86-
# Some libraries we use log to standard logging and not to loguru. To also get the logs from these frameworks, we
87-
# add a handler to the root logger of standard logging, that converts the log entries to loguru. This way
88-
# loguru has the final say regarding logging, and we don't get a mixture of both logging frameworks
89-
logging.basicConfig(handlers=[InterceptHandler()], level=logging.NOTSET, force=True)
90-
91-
# We have to replace the existing handlers from the loggers we want to intercept as well.
92-
for _log, _logger in logging.root.manager.loggerDict.items():
93-
# print("Checking logger: ", _log, " ", _logger)
94-
if not isinstance(_logger, Logger) or len(_logger.handlers) == 0:
95-
# logger not yet created or no custom handlers. Skipping
96-
continue
97-
for handler in _logger.handlers:
98-
if not isinstance(handler, logging.StreamHandler):
99-
# We only replace stream handlers, which write to the console
100-
# NullHandlers and other handlers are not replaced
101-
continue
102-
_logger.removeHandler(handler)
103-
_logger.addHandler(InterceptHandler())
104-
105-
# Prevent duplicate logs
106-
if _logger.propagate:
107-
logger.debug("Disable propagate for logger {}", _log)
108-
_logger.propagate = False
109-
110-
111-
class InterceptHandler(logging.Handler):
112-
"""
113-
A Handler for the standard python logging that sends all incoming logs to loguru. Taken from the loguru documentation
114-
https://loguru.readthedocs.io/en/stable/overview.html
115-
"""
116-
117-
def emit(self, record: logging.LogRecord) -> None:
118-
# Get corresponding Loguru level if it exists.
119-
level: str | int
120-
try:
121-
level = logger.level(record.levelname).name
122-
except ValueError:
123-
level = record.levelno
124-
125-
# Find caller from where originated the logged message.
126-
frame, depth = inspect.currentframe(), 0
127-
while frame and (depth == 0 or frame.f_code.co_filename == logging.__file__):
128-
frame = frame.f_back
129-
depth += 1
130-
131-
logger.opt(depth=depth, exception=record.exc_info).log(level, record.getMessage())
7+
__all__ = ["InterceptHandler", "setup_logging"]

0 commit comments

Comments
 (0)