diff --git a/src/google/adk/apps/app.py b/src/google/adk/apps/app.py index 67b2f458..50f1cf2d 100644 --- a/src/google/adk/apps/app.py +++ b/src/google/adk/apps/app.py @@ -13,7 +13,6 @@ # limitations under the License. from __future__ import annotations -from abc import ABC from typing import Optional from pydantic import BaseModel @@ -21,6 +20,7 @@ from pydantic import ConfigDict from pydantic import Field from ..agents.base_agent import BaseAgent +from ..apps.base_events_compactor import BaseEventsCompactor from ..plugins.base_plugin import BasePlugin from ..utils.feature_decorator import experimental @@ -50,3 +50,6 @@ class App(BaseModel): plugins: list[BasePlugin] = Field(default_factory=list) """The plugins in the application.""" + + event_compactor: Optional[BaseEventsCompactor] = None + """The event compactor strategy for the application.""" diff --git a/src/google/adk/apps/base_events_compactor.py b/src/google/adk/apps/base_events_compactor.py new file mode 100644 index 00000000..97e6611f --- /dev/null +++ b/src/google/adk/apps/base_events_compactor.py @@ -0,0 +1,50 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import abc +from typing import Optional + +from google.genai.types import Content + +from ..events.event import Event +from ..utils.feature_decorator import experimental + + +@experimental +class BaseEventsCompactor(abc.ABC): + """Base interface for compacting events.""" + + async def maybe_compact_events( + self, *, events: list[Event] + ) -> Optional[Content]: + """A list of uncompacted events, decide whether to compact. + + If no need to compact, return None. Otherwise, compact into a content and + return it. + + This method will summarize the events and return a new summray event + indicating the range of events it summarized. + + When sending events to the LLM, if a summary event is present, the events it + replaces (those identified in itssummary_range) should not be included. + + Args: + events: Events to compact. + agent_name: The name of the agent. + + Returns: + The new compacted content, or None if no compaction is needed. + """ + raise NotImplementedError() diff --git a/src/google/adk/events/event_actions.py b/src/google/adk/events/event_actions.py index a46ad16e..fb50a689 100644 --- a/src/google/adk/events/event_actions.py +++ b/src/google/adk/events/event_actions.py @@ -14,9 +14,9 @@ from __future__ import annotations -from typing import Any from typing import Optional +from google.genai.types import Content from pydantic import alias_generators from pydantic import BaseModel from pydantic import ConfigDict @@ -26,6 +26,23 @@ from ..auth.auth_tool import AuthConfig from ..tools.tool_confirmation import ToolConfirmation +class EventCompaction(BaseModel): + """The compaction of the events.""" + + model_config = ConfigDict( + extra='forbid', + alias_generator=alias_generators.to_camel, + populate_by_name=True, + ) + """The pydantic model config.""" + + compaction_range: Optional[tuple[float, float]] = None + """The sequence ID range of the events that are summarized, in the form(start_sequence_id, end_sequence_id)`""" + + compacted_content: Content + """The summarized content of the events.""" + + class EventActions(BaseModel): """Represents the actions attached to an event.""" @@ -72,3 +89,6 @@ class EventActions(BaseModel): ) """A dict of tool confirmation requested by this event, keyed by function call id.""" + + compaction: Optional[EventCompaction] = None + """The compaction of the events."""