From a051f7d6f603e1dd44cce1e2a70f59941b5f0b19 Mon Sep 17 00:00:00 2001 From: Rohit Malhotra Date: Tue, 3 Mar 2026 12:19:12 -0500 Subject: [PATCH] Add generic type hints to manager class declarations (#13174) Co-authored-by: openhands --- .../integrations/github/github_manager.py | 5 +++-- .../integrations/gitlab/gitlab_manager.py | 2 +- enterprise/integrations/jira/jira_manager.py | 2 +- .../integrations/jira_dc/jira_dc_manager.py | 2 +- .../integrations/linear/linear_manager.py | 2 +- enterprise/integrations/manager.py | 17 +++++++++++++---- enterprise/integrations/slack/slack_manager.py | 2 +- 7 files changed, 21 insertions(+), 11 deletions(-) diff --git a/enterprise/integrations/github/github_manager.py b/enterprise/integrations/github/github_manager.py index 88d31b8850..7d0501dc46 100644 --- a/enterprise/integrations/github/github_manager.py +++ b/enterprise/integrations/github/github_manager.py @@ -10,6 +10,7 @@ from integrations.github.github_view import ( GithubIssue, GithubIssueComment, GithubPRComment, + GithubViewType, ) from integrations.manager import Manager from integrations.models import ( @@ -43,7 +44,7 @@ from openhands.storage.data_models.secrets import Secrets from openhands.utils.async_utils import call_sync_from_async -class GithubManager(Manager): +class GithubManager(Manager[GithubViewType]): def __init__( self, token_manager: TokenManager, data_collector: GitHubDataCollector ): @@ -236,7 +237,7 @@ class GithubManager(Manager): logger.warning('Unsupported location') return - async def start_job(self, github_view: ResolverViewInterface): + async def start_job(self, github_view: GithubViewType): """Kick off a job with openhands agent. 1. Get user credential diff --git a/enterprise/integrations/gitlab/gitlab_manager.py b/enterprise/integrations/gitlab/gitlab_manager.py index 914823f8f5..be6cb49a6f 100644 --- a/enterprise/integrations/gitlab/gitlab_manager.py +++ b/enterprise/integrations/gitlab/gitlab_manager.py @@ -36,7 +36,7 @@ from openhands.server.types import ( from openhands.storage.data_models.secrets import Secrets -class GitlabManager(Manager): +class GitlabManager(Manager[GitlabViewType]): def __init__(self, token_manager: TokenManager, data_collector: None = None): self.token_manager = token_manager diff --git a/enterprise/integrations/jira/jira_manager.py b/enterprise/integrations/jira/jira_manager.py index 05e255651c..9223bcfa36 100644 --- a/enterprise/integrations/jira/jira_manager.py +++ b/enterprise/integrations/jira/jira_manager.py @@ -57,7 +57,7 @@ JIRA_CLOUD_API_URL = 'https://api.atlassian.com/ex/jira' OH_LABEL, INLINE_OH_LABEL = get_oh_labels(HOST) -class JiraManager(Manager): +class JiraManager(Manager[JiraViewInterface]): """Manager for processing Jira webhook events. This class orchestrates the flow from webhook receipt to conversation creation, diff --git a/enterprise/integrations/jira_dc/jira_dc_manager.py b/enterprise/integrations/jira_dc/jira_dc_manager.py index acbd1dfead..5adc1fbc75 100644 --- a/enterprise/integrations/jira_dc/jira_dc_manager.py +++ b/enterprise/integrations/jira_dc/jira_dc_manager.py @@ -42,7 +42,7 @@ from openhands.server.user_auth.user_auth import UserAuth from openhands.utils.http_session import httpx_verify_option -class JiraDcManager(Manager): +class JiraDcManager(Manager[JiraDcViewInterface]): def __init__(self, token_manager: TokenManager): self.token_manager = token_manager self.integration_store = JiraDcIntegrationStore.get_instance() diff --git a/enterprise/integrations/linear/linear_manager.py b/enterprise/integrations/linear/linear_manager.py index 1e78c2bc97..10f1b63c52 100644 --- a/enterprise/integrations/linear/linear_manager.py +++ b/enterprise/integrations/linear/linear_manager.py @@ -39,7 +39,7 @@ from openhands.server.user_auth.user_auth import UserAuth from openhands.utils.http_session import httpx_verify_option -class LinearManager(Manager): +class LinearManager(Manager[LinearViewInterface]): def __init__(self, token_manager: TokenManager): self.token_manager = token_manager self.integration_store = LinearIntegrationStore.get_instance() diff --git a/enterprise/integrations/manager.py b/enterprise/integrations/manager.py index f27804b1e8..550b4ca5c1 100644 --- a/enterprise/integrations/manager.py +++ b/enterprise/integrations/manager.py @@ -1,10 +1,13 @@ from abc import ABC, abstractmethod -from typing import Any +from typing import Any, Generic, TypeVar from integrations.models import Message, SourceType +# TypeVar for view types - each manager subclass specifies its own view type +ViewT = TypeVar('ViewT') -class Manager(ABC): + +class Manager(ABC, Generic[ViewT]): manager_type: SourceType @abstractmethod @@ -22,6 +25,12 @@ class Manager(ABC): raise NotImplementedError @abstractmethod - def start_job(self): - "Kick off a job with openhands agent" + def start_job(self, view: ViewT) -> None: + """Kick off a job with openhands agent. + + Args: + view: Integration-specific view object containing job context. + Each manager subclass accepts its own view type + (e.g., SlackViewInterface, JiraViewInterface, etc.) + """ raise NotImplementedError diff --git a/enterprise/integrations/slack/slack_manager.py b/enterprise/integrations/slack/slack_manager.py index 16a60d9e3a..34ee33b535 100644 --- a/enterprise/integrations/slack/slack_manager.py +++ b/enterprise/integrations/slack/slack_manager.py @@ -45,7 +45,7 @@ authorize_url_generator = AuthorizeUrlGenerator( ) -class SlackManager(Manager): +class SlackManager(Manager[SlackViewInterface]): def __init__(self, token_manager): self.token_manager = token_manager self.login_link = (