Skip to content

feat: integration/conn v1->v2 #1263

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 23 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
54eb407
feat: integration/conn v1->v2
Devanshusisodiya Feb 8, 2025
8bbfe42
fix: cleanup code
Devanshusisodiya Feb 8, 2025
64ea12d
fix: raise warning if force_integration param is passed
Devanshusisodiya Feb 10, 2025
2e7f54e
Merge with master
Devanshusisodiya Feb 10, 2025
b61ddb2
chore: fmt chk
Devanshusisodiya Feb 10, 2025
bae6dc0
Merge branch 'master' into feat/v1-v2-shift
Devanshusisodiya Feb 25, 2025
a0d6dce
docs: added comments
Devanshusisodiya Feb 25, 2025
4a9b332
test: fix example test
Devanshusisodiya Feb 25, 2025
8c38f15
test: added e2e test
Devanshusisodiya Feb 25, 2025
28231c9
fix: test classname
Devanshusisodiya Feb 25, 2025
cb4efdb
updated e2e test
Devanshusisodiya Feb 26, 2025
9f22d5d
fix: tests not running in ci
Devanshusisodiya Feb 26, 2025
0e28ebe
Merge branch 'master' into feat/v1-v2-shift
Devanshusisodiya Feb 26, 2025
ff67ce1
chore: fmt chk
Devanshusisodiya Feb 26, 2025
aeebe12
Revert "chore: fmt chk"
Devanshusisodiya Feb 26, 2025
b149777
chore: fmt chk
Devanshusisodiya Feb 26, 2025
1741af8
fix: review comments
Devanshusisodiya Feb 26, 2025
c8137b6
Merge branch 'master' into feat/v1-v2-shift
Devanshusisodiya Feb 27, 2025
85ceabe
Merge branch 'master' into feat/v1-v2-shift
Devanshusisodiya Feb 27, 2025
79ac8b8
fix: fail with pytest
Devanshusisodiya Feb 27, 2025
ace9c6d
Revert "fix: fail with pytest"
Devanshusisodiya Feb 27, 2025
594dc06
fix: fail with pytets
Devanshusisodiya Feb 27, 2025
e57e43e
fix: initiate_connection on toolset
Devanshusisodiya Feb 27, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 11 additions & 26 deletions python/composio/client/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,7 @@ def initiate_connection(
redirect_url: t.Optional[str] = None,
integration: t.Optional[IntegrationModel] = None,
use_composio_auth: bool = True,
force_new_integration: bool = False,
force_new_integration: bool = False, # pylint: disable=unused-argument
connected_account_params: t.Optional[t.Dict] = None,
labels: t.Optional[t.List] = None,
) -> ConnectionRequestModel:
Expand All @@ -445,38 +445,23 @@ def initiate_connection(

app = self.client.apps.get(name=app_name_str)
timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
if integration is None and auth_mode is not None:
if auth_mode not in AUTH_SCHEMES:
raise ComposioClientError(
f"'auth_mode' should be one of {AUTH_SCHEMES}"
)
auth_mode = t.cast(AuthSchemeType, auth_mode)
if "OAUTH" not in auth_mode:
use_composio_auth = False
integration = self.client.integrations.create(
app_id=app.appId,
name=f"{app_name}_{timestamp}",
auth_mode=auth_mode,
auth_config=auth_config,
use_composio_auth=use_composio_auth,
force_new_integration=force_new_integration,
)

if integration is None and auth_mode is None:
integration = self.client.integrations.create(
app_id=app.appId,
auth_config=auth_config,
name=f"{app_name}_{timestamp}",
use_composio_auth=use_composio_auth,
force_new_integration=force_new_integration,
)
if auth_mode is None:
raise ComposioClientError(f"'auth_mode' should be one of {AUTH_SCHEMES}")

auth_mode = t.cast(AuthSchemeType, auth_mode)

return self.client.connected_accounts.initiate(
integration_id=t.cast(IntegrationModel, integration).id,
integration_id=integration.id if integration is not None else None,
entity_id=self.id,
params=connected_account_params,
labels=labels,
redirect_url=redirect_url,
app_unique_key=app.name,
name=f"{app_name}_{timestamp}",
auth_mode=auth_mode,
auth_config=auth_config,
use_composio_auth=use_composio_auth,
)


Expand Down
63 changes: 40 additions & 23 deletions python/composio/client/collections.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ class ConnectedAccounts(Collection[ConnectedAccountModel]):

model = ConnectedAccountModel
endpoint = v1 / "connectedAccounts"
endpoint_v2 = v2 / "connectedAccounts"

@t.overload # type: ignore
def get(self) -> t.List[ConnectedAccountModel]:
Expand Down Expand Up @@ -239,26 +240,43 @@ def get(

def initiate(
self,
integration_id: str,
integration_id: t.Optional[str] = None,
app_unique_key: t.Optional[str] = None,
entity_id: t.Optional[str] = None,
params: t.Optional[t.Dict] = None,
labels: t.Optional[t.List] = None,
redirect_url: t.Optional[str] = None,
name: t.Optional[str] = None,
auth_mode: t.Optional["AuthSchemeType"] = None,
auth_config: t.Optional[t.Dict[str, t.Any]] = None,
use_composio_auth: bool = False,
) -> ConnectionRequestModel:
"""Initiate a new connected account."""
response = self._raise_if_required(
response=self.client.http.post(
url=str(self.endpoint),
url=str(self.endpoint_v2 / "initiateConnection"),
json={
"integrationId": integration_id,
"userUuid": entity_id,
"data": params or {},
"labels": labels or [],
"redirectUri": redirect_url,
"app": {
"integrationId": integration_id,
"uniqueKey": (
app_unique_key.lower() if app_unique_key else app_unique_key
),
},
"config": {
"name": name,
"authScheme": auth_mode,
"integrationSecrets": auth_config or {},
"useComposioAuth": use_composio_auth,
},
"connection": {
"entityId": entity_id,
"initiateData": params or {},
"extra": {"redirectUrl": redirect_url, "labels": labels or []},
},
},
)
)
return ConnectionRequestModel(**response.json())
return ConnectionRequestModel(**response.json().get("connectionResponse"))

def info(self, connection_id: str) -> ConnectionParams:
response = self._raise_if_required(
Expand Down Expand Up @@ -1474,50 +1492,49 @@ class Integrations(Collection[IntegrationModel]):

model = IntegrationModel
endpoint = v1.integrations
endpoint_v2 = v2.integrations

def create(
self,
app_id: str,
app_unique_key: str,
name: t.Optional[str] = None,
auth_mode: t.Optional["AuthSchemeType"] = None,
auth_config: t.Optional[t.Dict[str, t.Any]] = None,
use_composio_auth: bool = False,
force_new_integration: bool = False,
) -> IntegrationModel:
"""
Create a new integration

:param app_unique_key: App unique key string.
:param app_id: App ID string.
:param name: Name of the integration.
:param auth_param: Auth mode string.
:param auth_config: Authentication configuration.
:param use_composio_auth: Whether to use default composio auth or not
:return: Integration model created by the request.
"""
request = {
"appId": app_id,
"useComposioAuth": use_composio_auth,
request: t.Dict[str, t.Any] = {
"app": {"uniqueKey": app_unique_key.lower()},
"config": {},
}

if use_composio_auth is not None:
request["config"]["useComposioAuth"] = use_composio_auth
if name is not None:
request["name"] = name

request["config"]["name"] = name
if auth_mode is not None:
request["authScheme"] = auth_mode

request["config"]["authScheme"] = auth_mode
if auth_config is not None:
request["authConfig"] = auth_config or {}

if force_new_integration:
request["forceNewIntegration"] = force_new_integration
request["config"]["integrationSecrets"] = auth_config

response = self._raise_if_required(
response=self.client.http.post(
url=str(self.endpoint),
url=str(self.endpoint_v2 / "create"),
json=request,
)
)
return IntegrationModel(**response.json())

return self.model(**response.json())

def remove(self, id: str) -> None:
self.client.http.delete(url=str(self.endpoint / id))
Expand Down
12 changes: 9 additions & 3 deletions python/composio/client/endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,21 +116,27 @@ class _Integrations(Endpoint):

class _V2(Endpoint):
"""
Endpoint: /v1
Endpoint: /v2
"""

class _Integrations(Endpoint):
"""
Endpoint /v2/integrations
"""

class _Actions(Endpoint):
"""
Endpoint /v1/actions
Endpoint /v2/actions
"""

class _Triggers(Endpoint):
"""
Endpoint /v1/triggers
Endpoint /v2/triggers
"""

triggers: _Triggers
actions: _Actions
integrations: _Integrations


v1 = _V1(endpoint="v1")
Expand Down
5 changes: 2 additions & 3 deletions python/composio/tools/toolset.py
Original file line number Diff line number Diff line change
Expand Up @@ -1260,17 +1260,16 @@ def create_integration(
auth_mode: t.Optional[AuthSchemeType] = None,
auth_config: t.Optional[t.Dict[str, t.Any]] = None,
use_composio_oauth_app: bool = True,
force_new_integration: bool = False,
force_new_integration: bool = False, # pylint: disable=unused-argument
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deprecation warning

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added.

) -> IntegrationModel:
app_data = self.client.apps.get(name=str(app))
timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
return self.client.integrations.create(
app_id=app_data.appId,
app_unique_key=app_data.name,
name=f"{app}_{timestamp}",
auth_mode=auth_mode,
auth_config=auth_config,
use_composio_auth=use_composio_oauth_app,
force_new_integration=force_new_integration,
)

def initiate_connection(
Expand Down