diff --git a/python/composio/cli/add.py b/python/composio/cli/add.py index 0c084e603ca..7257d54a00d 100644 --- a/python/composio/cli/add.py +++ b/python/composio/cli/add.py @@ -238,12 +238,16 @@ def add_integration( AuthSchemeType, click.prompt( "Select auth mode: ", - type=click.Choice(choices=list(auth_modes)), + type=click.Choice(choices=t.cast(t.List[str], auth_modes)), ), ) auth_scheme = auth_modes[auth_mode] - if auth_mode.lower() in ("basic", "api_key", "bearer_token"): + if auth_mode is not None and auth_mode.lower() in ( + "basic", + "api_key", + "bearer_token", + ): return _handle_basic_auth( entity=entity, app_name=name, diff --git a/python/composio/client/collections.py b/python/composio/client/collections.py index 622608203d5..6c7d4176247 100644 --- a/python/composio/client/collections.py +++ b/python/composio/client/collections.py @@ -293,8 +293,10 @@ class AuthSchemeField(BaseModel): class AppAuthScheme(BaseModel): """App authenticatio scheme.""" - scheme_name: str - auth_mode: AuthSchemeType + scheme_name: t.Optional[str] = None + name: t.Optional[str] = None + auth_mode: t.Optional[AuthSchemeType] = None + mode: t.Optional[str] = None fields: t.List[AuthSchemeField] proxy: t.Optional[t.Dict] = None @@ -342,8 +344,13 @@ def get(self) -> t.List[AppModel]: def get(self, name: t.Optional[str] = None) -> AppModel: """Get a specific app.""" - def get(self, name: t.Optional[str] = None) -> t.Union[AppModel, t.List[AppModel]]: + def get( + self, + name: t.Optional[str] = None, + ) -> t.Union[AppModel, t.List[AppModel]]: """Get apps.""" + queries = {"additionalFields": "auth_schemes,test_connectors"} + if name is not None: return self.model( **self._raise_if_required( @@ -353,7 +360,13 @@ def get(self, name: t.Optional[str] = None) -> t.Union[AppModel, t.List[AppModel ).json() ) - return super().get(queries={}) + apps = super().get(queries=queries) + for app in apps: + if app.auth_schemes is not None: + for auth_scheme in app.auth_schemes: + if auth_scheme.mode is not None: + auth_scheme.auth_mode = t.cast(AuthSchemeType, auth_scheme.mode) + return apps class TypeModel(BaseModel): diff --git a/python/composio/tools/toolset.py b/python/composio/tools/toolset.py index 9bf95649281..b7e32628ed4 100644 --- a/python/composio/tools/toolset.py +++ b/python/composio/tools/toolset.py @@ -870,6 +870,7 @@ def get_apps( no_auth: t.Optional[bool] = None, include_local: bool = True, ) -> t.List[AppModel]: + # added type ignore since method overload was not being referenced apps = self.client.apps.get() if no_auth is not None: apps = [a for a in apps if a.no_auth is no_auth] @@ -1051,6 +1052,10 @@ def get_expected_params_for_user( # without user inputs to create an integratuib, if yes then create # an integration and return params from there. for scheme in app_data.auth_schemes or []: + if scheme.auth_mode is None: + raise ComposioSDKError( + message=f"No auth scheme found for app `{app_data.name}`" + ) if auth_scheme is not None and auth_scheme != scheme.auth_mode.upper(): continue if self._can_use_auth_scheme_without_user_input( @@ -1083,6 +1088,10 @@ def fetch_expected_integration_params( ) -> t.List[AuthSchemeField]: """Fetch expected integration params for creating an integration.""" for scheme in app.auth_schemes or []: + if scheme.auth_mode is None: + raise ComposioSDKError( + message=f"No auth scheme found for app `{app.name}`" + ) if auth_scheme != scheme.auth_mode.upper(): continue return [f for f in scheme.fields if not f.expected_from_customer] @@ -1154,7 +1163,7 @@ def initiate_connection( ).id except NoItemsFound: auth_config, use_composio_auth = self._validate_auth_config( - app, auth_scheme, auth_config + app, t.cast(AuthSchemeType, auth_scheme), auth_config ) integration = self.create_integration( app=app, diff --git a/python/tests/test_tools/test_toolset.py b/python/tests/test_tools/test_toolset.py index b9a728b618b..3050015aae3 100644 --- a/python/tests/test_tools/test_toolset.py +++ b/python/tests/test_tools/test_toolset.py @@ -11,6 +11,7 @@ from pydantic import BaseModel, Field from composio import Action, App +from composio.client.collections import AUTH_SCHEMES from composio.exceptions import ApiKeyNotProvidedError, ComposioSDKError from composio.tools.base.abs import action_registry, tool_registry from composio.tools.base.runtime import action as custom_action @@ -67,6 +68,18 @@ def test_uninitialize_app() -> None: ComposioToolSet().get_action_schemas(actions=[Action.ATTIO_UPDATE_A_LIST]) +def test_get_apps() -> None: + toolset = ComposioToolSet() + apps = toolset.get_apps() + for app in apps: + if app.no_auth is False: + auth_app = app + break + if auth_app.auth_schemes: + for auth_scheme in auth_app.auth_schemes: + assert auth_scheme.auth_mode in AUTH_SCHEMES + + class TestValidateTools: toolset: ComposioToolSet package = "somepackage1"