|  | @@ -0,0 +1,101 @@
 | 
	
		
			
				|  |  | +import json
 | 
	
		
			
				|  |  | +from datetime import datetime, timedelta
 | 
	
		
			
				|  |  | +from typing import Any, Union
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +import requests
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +from core.tools.entities.tool_entities import ToolInvokeMessage
 | 
	
		
			
				|  |  | +from core.tools.tool.builtin_tool import BuiltinTool
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +class GitlabCommitsTool(BuiltinTool):
 | 
	
		
			
				|  |  | +    def _invoke(self, 
 | 
	
		
			
				|  |  | +                user_id: str,
 | 
	
		
			
				|  |  | +                tool_parameters: dict[str, Any]
 | 
	
		
			
				|  |  | +        ) -> Union[ToolInvokeMessage, list[ToolInvokeMessage]]:
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        project = tool_parameters.get('project', '')
 | 
	
		
			
				|  |  | +        employee = tool_parameters.get('employee', '')
 | 
	
		
			
				|  |  | +        start_time = tool_parameters.get('start_time', '')
 | 
	
		
			
				|  |  | +        end_time = tool_parameters.get('end_time', '')
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if not project:
 | 
	
		
			
				|  |  | +            return self.create_text_message('Project is required')
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if not start_time:
 | 
	
		
			
				|  |  | +            start_time = (datetime.utcnow() - timedelta(days=1)).isoformat()
 | 
	
		
			
				|  |  | +        if not end_time:
 | 
	
		
			
				|  |  | +            end_time = datetime.utcnow().isoformat()
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        access_token = self.runtime.credentials.get('access_tokens')
 | 
	
		
			
				|  |  | +        site_url = self.runtime.credentials.get('site_url')
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if 'access_tokens' not in self.runtime.credentials or not self.runtime.credentials.get('access_tokens'):
 | 
	
		
			
				|  |  | +            return self.create_text_message("Gitlab API Access Tokens is required.")
 | 
	
		
			
				|  |  | +        if 'site_url' not in self.runtime.credentials or not self.runtime.credentials.get('site_url'):
 | 
	
		
			
				|  |  | +            site_url = 'https://gitlab.com'
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        # Get commit content
 | 
	
		
			
				|  |  | +        result = self.fetch(user_id, site_url, access_token, project, employee, start_time, end_time)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        return self.create_text_message(json.dumps(result, ensure_ascii=False))
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    def fetch(self,user_id: str, site_url: str, access_token: str, project: str, employee: str = None, start_time: str = '', end_time: str = '') -> list[dict[str, Any]]:
 | 
	
		
			
				|  |  | +        domain = site_url
 | 
	
		
			
				|  |  | +        headers = {"PRIVATE-TOKEN": access_token}
 | 
	
		
			
				|  |  | +        results = []
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        try:
 | 
	
		
			
				|  |  | +            # Get all of projects
 | 
	
		
			
				|  |  | +            url = f"{domain}/api/v4/projects"
 | 
	
		
			
				|  |  | +            response = requests.get(url, headers=headers)
 | 
	
		
			
				|  |  | +            response.raise_for_status()
 | 
	
		
			
				|  |  | +            projects = response.json()
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            filtered_projects = [p for p in projects if project == "*" or p['name'] == project]
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            for project in filtered_projects:
 | 
	
		
			
				|  |  | +                project_id = project['id']
 | 
	
		
			
				|  |  | +                project_name = project['name']
 | 
	
		
			
				|  |  | +                print(f"Project: {project_name}")
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                # Get all of proejct commits
 | 
	
		
			
				|  |  | +                commits_url = f"{domain}/api/v4/projects/{project_id}/repository/commits"
 | 
	
		
			
				|  |  | +                params = {
 | 
	
		
			
				|  |  | +                    'since': start_time,
 | 
	
		
			
				|  |  | +                    'until': end_time
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                if employee:
 | 
	
		
			
				|  |  | +                    params['author'] = employee
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                commits_response = requests.get(commits_url, headers=headers, params=params)
 | 
	
		
			
				|  |  | +                commits_response.raise_for_status()
 | 
	
		
			
				|  |  | +                commits = commits_response.json()
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                for commit in commits:
 | 
	
		
			
				|  |  | +                    commit_sha = commit['id']
 | 
	
		
			
				|  |  | +                    print(f"\tCommit SHA: {commit_sha}")
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                    diff_url = f"{domain}/api/v4/projects/{project_id}/repository/commits/{commit_sha}/diff"
 | 
	
		
			
				|  |  | +                    diff_response = requests.get(diff_url, headers=headers)
 | 
	
		
			
				|  |  | +                    diff_response.raise_for_status()
 | 
	
		
			
				|  |  | +                    diffs = diff_response.json()
 | 
	
		
			
				|  |  | +                    
 | 
	
		
			
				|  |  | +                    for diff in diffs:
 | 
	
		
			
				|  |  | +                        # Caculate code lines of changed
 | 
	
		
			
				|  |  | +                        added_lines = diff['diff'].count('\n+')
 | 
	
		
			
				|  |  | +                        removed_lines = diff['diff'].count('\n-')
 | 
	
		
			
				|  |  | +                        total_changes = added_lines + removed_lines
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                        if total_changes > 1:
 | 
	
		
			
				|  |  | +                            final_code = ''.join([line[1:] for line in diff['diff'].split('\n') if line.startswith('+') and not line.startswith('+++')])
 | 
	
		
			
				|  |  | +                            results.append({
 | 
	
		
			
				|  |  | +                                "project": project_name,
 | 
	
		
			
				|  |  | +                                "commit_sha": commit_sha,
 | 
	
		
			
				|  |  | +                                "diff": final_code
 | 
	
		
			
				|  |  | +                            })
 | 
	
		
			
				|  |  | +                            print(f"Commit code:{final_code}")
 | 
	
		
			
				|  |  | +        except requests.RequestException as e:
 | 
	
		
			
				|  |  | +            print(f"Error fetching data from GitLab: {e}")
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        return results
 |