From 812db81a8b033a40172cc019b1f1ecc90e6bcafb Mon Sep 17 00:00:00 2001 From: Google Team Member Date: Mon, 29 Jun 2026 22:12:57 -0700 Subject: [PATCH] feat(interactions): add CodeMenderAgentConfig PiperOrigin-RevId: 940223251 --- .../_gaos/resources/interactions/__init__.py | 4 + .../codemenderagentconfig/__init__.py | 27 ++ .../find_request/__init__.py | 21 ++ .../fix_request/__init__.py | 21 ++ .../_gaos/types/interactions/__init__.py | 34 +++ .../interactions/codemenderagentconfig.py | 260 ++++++++++++++++++ .../interactions/createagentinteraction.py | 10 +- .../_gaos/types/interactions/filecontent.py | 58 ++++ .../_gaos/types/interactions/interaction.py | 15 +- 9 files changed, 446 insertions(+), 4 deletions(-) create mode 100644 google/genai/_gaos/resources/interactions/codemenderagentconfig/__init__.py create mode 100644 google/genai/_gaos/resources/interactions/codemenderagentconfig/find_request/__init__.py create mode 100644 google/genai/_gaos/resources/interactions/codemenderagentconfig/fix_request/__init__.py create mode 100644 google/genai/_gaos/types/interactions/codemenderagentconfig.py create mode 100644 google/genai/_gaos/types/interactions/filecontent.py diff --git a/google/genai/_gaos/resources/interactions/__init__.py b/google/genai/_gaos/resources/interactions/__init__.py index 05f44f3a0..7edfd2134 100644 --- a/google/genai/_gaos/resources/interactions/__init__.py +++ b/google/genai/_gaos/resources/interactions/__init__.py @@ -35,6 +35,7 @@ from ...types.interactions.codeexecutioncallarguments import CodeExecutionCallArguments from ...types.interactions.codeexecutioncallstep import CodeExecutionCallStep from ...types.interactions.codeexecutionresultstep import CodeExecutionResultStep +from ...types.interactions.codemenderagentconfig import CodeMenderAgentConfig from ...types.interactions.content import Content from ...types.interactions.createagentinteraction import ( CreateAgentInteractionParam as CreateAgentInteractionParamsNonStreaming, @@ -100,6 +101,7 @@ from ...types.interactions.videoresponseformat import VideoResponseFormat from ...types.interactions.webhookconfig import WebhookConfig from . import codeexecutioncallstep +from . import codemenderagentconfig from . import environment from . import errorevent from . import googlemapscallstep @@ -130,6 +132,7 @@ "CodeExecutionCallArguments", "CodeExecutionCallStep", "CodeExecutionResultStep", + "CodeMenderAgentConfig", "Content", "CreateAgentInteractionParamsNonStreaming", "CreateAgentInteractionParamsStreaming", @@ -197,6 +200,7 @@ "VideoResponseFormat", "WebhookConfig", "codeexecutioncallstep", + "codemenderagentconfig", "environment", "errorevent", "googlemapscallstep", diff --git a/google/genai/_gaos/resources/interactions/codemenderagentconfig/__init__.py b/google/genai/_gaos/resources/interactions/codemenderagentconfig/__init__.py new file mode 100644 index 000000000..1bd3b1c87 --- /dev/null +++ b/google/genai/_gaos/resources/interactions/codemenderagentconfig/__init__.py @@ -0,0 +1,27 @@ +# Copyright 2026 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. +# +# pyformat: disable + +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from ....types.interactions.codemenderagentconfig import ( + FindRequest, + FixRequest, + SessionConfig, +) +from . import find_request +from . import fix_request + +__all__ = ["FindRequest", "FixRequest", "SessionConfig", "find_request", "fix_request"] diff --git a/google/genai/_gaos/resources/interactions/codemenderagentconfig/find_request/__init__.py b/google/genai/_gaos/resources/interactions/codemenderagentconfig/find_request/__init__.py new file mode 100644 index 000000000..1b40e3663 --- /dev/null +++ b/google/genai/_gaos/resources/interactions/codemenderagentconfig/find_request/__init__.py @@ -0,0 +1,21 @@ +# Copyright 2026 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. +# +# pyformat: disable + +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from .....types.interactions.filecontent import FileContent as SourceFile + +__all__ = ["SourceFile"] diff --git a/google/genai/_gaos/resources/interactions/codemenderagentconfig/fix_request/__init__.py b/google/genai/_gaos/resources/interactions/codemenderagentconfig/fix_request/__init__.py new file mode 100644 index 000000000..1b40e3663 --- /dev/null +++ b/google/genai/_gaos/resources/interactions/codemenderagentconfig/fix_request/__init__.py @@ -0,0 +1,21 @@ +# Copyright 2026 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. +# +# pyformat: disable + +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from .....types.interactions.filecontent import FileContent as SourceFile + +__all__ = ["SourceFile"] diff --git a/google/genai/_gaos/types/interactions/__init__.py b/google/genai/_gaos/types/interactions/__init__.py index e66a6e8bd..7287f180a 100644 --- a/google/genai/_gaos/types/interactions/__init__.py +++ b/google/genai/_gaos/types/interactions/__init__.py @@ -53,6 +53,17 @@ CodeExecutionResultStep, CodeExecutionResultStepParam, ) + from .codemenderagentconfig import ( + CodeMenderAgentConfig, + CodeMenderAgentConfigParam, + FindRequest, + FindRequestParam, + FixRequest, + FixRequestParam, + Mode, + SessionConfig, + SessionConfigParam, + ) from .computeruse import ( ComputerUse, ComputerUseParam, @@ -113,6 +124,7 @@ from .errorevent import ErrorEvent, ErrorEventTypedDict from .exaaisearchconfig import ExaAISearchConfig, ExaAISearchConfigParam from .filecitation import FileCitation, FileCitationParam + from .filecontent import FileContent, FileContentParam from .filesearch import FileSearch, FileSearchParam from .filesearchcalldelta import FileSearchCallDelta, FileSearchCallDeltaTypedDict from .filesearchcallstep import FileSearchCallStep, FileSearchCallStepParam @@ -406,6 +418,8 @@ "CodeExecutionResultDeltaTypedDict", "CodeExecutionResultStep", "CodeExecutionResultStepParam", + "CodeMenderAgentConfig", + "CodeMenderAgentConfigParam", "ComputerUse", "ComputerUseParam", "Content", @@ -451,6 +465,8 @@ "ExaAISearchConfigParam", "FileCitation", "FileCitationParam", + "FileContent", + "FileContentParam", "FileSearch", "FileSearchCallDelta", "FileSearchCallDeltaTypedDict", @@ -465,6 +481,10 @@ "FileSearchResultTypedDict", "Filter", "FilterParam", + "FindRequest", + "FindRequestParam", + "FixRequest", + "FixRequestParam", "Function", "FunctionCallStep", "FunctionCallStepParam", @@ -585,6 +605,7 @@ "MediaResolution", "ModalityTokens", "ModalityTokensTypedDict", + "Mode", "Model", "ModelOutputStep", "ModelOutputStepParam", @@ -612,6 +633,8 @@ "ReviewSnippet", "ReviewSnippetParam", "ServiceTier", + "SessionConfig", + "SessionConfigParam", "Source", "SourceParam", "SourceType", @@ -747,6 +770,15 @@ "CodeExecutionResultDeltaTypedDict": ".codeexecutionresultdelta", "CodeExecutionResultStep": ".codeexecutionresultstep", "CodeExecutionResultStepParam": ".codeexecutionresultstep", + "CodeMenderAgentConfig": ".codemenderagentconfig", + "CodeMenderAgentConfigParam": ".codemenderagentconfig", + "FindRequest": ".codemenderagentconfig", + "FindRequestParam": ".codemenderagentconfig", + "FixRequest": ".codemenderagentconfig", + "FixRequestParam": ".codemenderagentconfig", + "Mode": ".codemenderagentconfig", + "SessionConfig": ".codemenderagentconfig", + "SessionConfigParam": ".codemenderagentconfig", "ComputerUse": ".computeruse", "ComputerUseParam": ".computeruse", "DisabledSafetyPolicy": ".computeruse", @@ -799,6 +831,8 @@ "ExaAISearchConfigParam": ".exaaisearchconfig", "FileCitation": ".filecitation", "FileCitationParam": ".filecitation", + "FileContent": ".filecontent", + "FileContentParam": ".filecontent", "FileSearch": ".filesearch", "FileSearchParam": ".filesearch", "FileSearchCallDelta": ".filesearchcalldelta", diff --git a/google/genai/_gaos/types/interactions/codemenderagentconfig.py b/google/genai/_gaos/types/interactions/codemenderagentconfig.py new file mode 100644 index 000000000..cdd7859fa --- /dev/null +++ b/google/genai/_gaos/types/interactions/codemenderagentconfig.py @@ -0,0 +1,260 @@ +# Copyright 2026 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. +# +# pyformat: disable + +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from .. import BaseModel, UNSET_SENTINEL, UnrecognizedStr +from ...utils import validate_const +from .filecontent import FileContent, FileContentParam +import pydantic +from pydantic import model_serializer +from pydantic.functional_validators import AfterValidator +from typing import List, Literal, Optional, Union +from typing_extensions import Annotated, NotRequired, TypedDict + + +Mode = Union[ + Literal[ + "scan", + "verify", + ], + UnrecognizedStr, +] +r"""The mode of the find session.""" + + +class FindRequestParam(TypedDict): + r"""Parameters for finding vulnerabilities.""" + + source_files: NotRequired[List[FileContentParam]] + r"""A list of source files to provide as context for the scan.""" + finding_id: NotRequired[str] + r"""The identifier of a specific finding to verify. This is primarily used in + VERIFY mode to focus the agent's execution-based validation on a single + vulnerability. + """ + description: NotRequired[str] + r"""Additional context or custom instructions provided by the user to guide + the vulnerability analysis. + """ + mode: NotRequired[Mode] + r"""The mode of the find session.""" + + +class FindRequest(BaseModel): + r"""Parameters for finding vulnerabilities.""" + + source_files: Optional[List[FileContent]] = None + r"""A list of source files to provide as context for the scan.""" + + finding_id: Optional[str] = None + r"""The identifier of a specific finding to verify. This is primarily used in + VERIFY mode to focus the agent's execution-based validation on a single + vulnerability. + """ + + description: Optional[str] = None + r"""Additional context or custom instructions provided by the user to guide + the vulnerability analysis. + """ + + mode: Optional[Mode] = None + r"""The mode of the find session.""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["source_files", "finding_id", "description", "mode"]) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k, serialized.get(n)) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m + + +class FixRequestParam(TypedDict): + r"""Parameters for fixing vulnerabilities.""" + + source_files: NotRequired[List[FileContentParam]] + r"""A list of source files providing context for the remediation. These files + are typically the ones containing the identified vulnerability. + """ + finding_id: NotRequired[str] + r"""The identifier of the specific security finding to be remediated. This ID + maps to a previously discovered vulnerability. + """ + description: NotRequired[str] + r"""Additional context or custom instructions provided by the user to guide + the patch generation process. + """ + + +class FixRequest(BaseModel): + r"""Parameters for fixing vulnerabilities.""" + + source_files: Optional[List[FileContent]] = None + r"""A list of source files providing context for the remediation. These files + are typically the ones containing the identified vulnerability. + """ + + finding_id: Optional[str] = None + r"""The identifier of the specific security finding to be remediated. This ID + maps to a previously discovered vulnerability. + """ + + description: Optional[str] = None + r"""Additional context or custom instructions provided by the user to guide + the patch generation process. + """ + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["source_files", "finding_id", "description"]) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k, serialized.get(n)) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m + + +class SessionConfigParam(TypedDict): + r"""Optional session-specific configurations to override default agent + behavior. + """ + + max_rounds: NotRequired[int] + r"""The maximum number of interaction rounds the agent is allowed to perform + before reaching a timeout. + """ + + +class SessionConfig(BaseModel): + r"""Optional session-specific configurations to override default agent + behavior. + """ + + max_rounds: Optional[int] = None + r"""The maximum number of interaction rounds the agent is allowed to perform + before reaching a timeout. + """ + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["max_rounds"]) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k, serialized.get(n)) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m + + +class CodeMenderAgentConfigParam(TypedDict): + r"""Configuration for the CodeMender agent.""" + + type: Literal["code-mender"] + find_request: NotRequired[FindRequestParam] + r"""Parameters for finding vulnerabilities.""" + fix_request: NotRequired[FixRequestParam] + r"""Parameters for fixing vulnerabilities.""" + session_id: NotRequired[str] + r"""Parameter for grouping multiple interactions that belong to + the same CodeMender session. + """ + session_config: NotRequired[SessionConfigParam] + r"""Optional session-specific configurations to override default agent + behavior. + """ + model: NotRequired[str] + r"""The name of the model to use for the CodeMender agent. One + CodeMender session will only use one model. + """ + + +class CodeMenderAgentConfig(BaseModel): + r"""Configuration for the CodeMender agent.""" + + type: Annotated[ + Annotated[ + Literal["code-mender"], AfterValidator(validate_const("code-mender")) + ], + pydantic.Field(alias="type"), + ] = "code-mender" + + find_request: Optional[FindRequest] = None + r"""Parameters for finding vulnerabilities.""" + + fix_request: Optional[FixRequest] = None + r"""Parameters for fixing vulnerabilities.""" + + session_id: Optional[str] = None + r"""Parameter for grouping multiple interactions that belong to + the same CodeMender session. + """ + + session_config: Optional[SessionConfig] = None + r"""Optional session-specific configurations to override default agent + behavior. + """ + + model: Optional[str] = None + r"""The name of the model to use for the CodeMender agent. One + CodeMender session will only use one model. + """ + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set( + ["find_request", "fix_request", "session_id", "session_config", "model"] + ) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k, serialized.get(n)) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m + + +try: + CodeMenderAgentConfig.model_rebuild() +except NameError: + pass diff --git a/google/genai/_gaos/types/interactions/createagentinteraction.py b/google/genai/_gaos/types/interactions/createagentinteraction.py index 18736d09e..99b0ece8f 100644 --- a/google/genai/_gaos/types/interactions/createagentinteraction.py +++ b/google/genai/_gaos/types/interactions/createagentinteraction.py @@ -19,6 +19,7 @@ from __future__ import annotations from .. import BaseModel, UNSET_SENTINEL from .agentoption import AgentOption +from .codemenderagentconfig import CodeMenderAgentConfig, CodeMenderAgentConfigParam from .deepresearchagentconfig import ( DeepResearchAgentConfig, DeepResearchAgentConfigParam, @@ -64,13 +65,18 @@ CreateAgentInteractionAgentConfigParam = TypeAliasType( "CreateAgentInteractionAgentConfigParam", - Union[DynamicAgentConfigParam, DeepResearchAgentConfigParam], + Union[ + DynamicAgentConfigParam, + DeepResearchAgentConfigParam, + CodeMenderAgentConfigParam, + ], ) r"""Configuration parameters for the agent interaction.""" CreateAgentInteractionAgentConfig = Annotated[ - Union[DynamicAgentConfig, DeepResearchAgentConfig], Field(discriminator="type") + Union[DynamicAgentConfig, DeepResearchAgentConfig, CodeMenderAgentConfig], + Field(discriminator="type"), ] r"""Configuration parameters for the agent interaction.""" diff --git a/google/genai/_gaos/types/interactions/filecontent.py b/google/genai/_gaos/types/interactions/filecontent.py new file mode 100644 index 000000000..800c3d062 --- /dev/null +++ b/google/genai/_gaos/types/interactions/filecontent.py @@ -0,0 +1,58 @@ +# Copyright 2026 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. +# +# pyformat: disable + +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from .. import BaseModel, UNSET_SENTINEL +from pydantic import model_serializer +from typing import Optional +from typing_extensions import NotRequired, TypedDict + + +class FileContentParam(TypedDict): + r"""Content of a single file in the codebase.""" + + path: NotRequired[str] + r"""The relative path of the file from the project root.""" + content: NotRequired[str] + r"""The UTF-8 encoded text content of the file.""" + + +class FileContent(BaseModel): + r"""Content of a single file in the codebase.""" + + path: Optional[str] = None + r"""The relative path of the file from the project root.""" + + content: Optional[str] = None + r"""The UTF-8 encoded text content of the file.""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["path", "content"]) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k, serialized.get(n)) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m diff --git a/google/genai/_gaos/types/interactions/interaction.py b/google/genai/_gaos/types/interactions/interaction.py index 2f3d33fab..0d5e7b3fe 100644 --- a/google/genai/_gaos/types/interactions/interaction.py +++ b/google/genai/_gaos/types/interactions/interaction.py @@ -21,6 +21,7 @@ from ...utils.unions import parse_open_union from .agentoption import AgentOption from .audiocontent import AudioContent, AudioContentParam +from .codemenderagentconfig import CodeMenderAgentConfig, CodeMenderAgentConfigParam from .deepresearchagentconfig import ( DeepResearchAgentConfig, DeepResearchAgentConfigParam, @@ -89,7 +90,11 @@ InteractionAgentConfigTypedDict = TypeAliasType( "InteractionAgentConfigTypedDict", - Union[DynamicAgentConfigParam, DeepResearchAgentConfigParam], + Union[ + DynamicAgentConfigParam, + DeepResearchAgentConfigParam, + CodeMenderAgentConfigParam, + ], ) r"""Configuration parameters for the agent interaction.""" @@ -107,11 +112,17 @@ class UnknownInteractionAgentConfig(BaseModel): _INTERACTION_AGENT_CONFIG_VARIANTS: dict[str, Any] = { "dynamic": DynamicAgentConfig, "deep-research": DeepResearchAgentConfig, + "code-mender": CodeMenderAgentConfig, } InteractionAgentConfig = Annotated[ - Union[DynamicAgentConfig, DeepResearchAgentConfig, UnknownInteractionAgentConfig], + Union[ + DynamicAgentConfig, + DeepResearchAgentConfig, + CodeMenderAgentConfig, + UnknownInteractionAgentConfig, + ], BeforeValidator( partial( parse_open_union,