mirror of
https://github.com/langgenius/dify-plugin-sdks.git
synced 2026-07-22 10:25:23 -04:00
c6f83a63e1
* chore: fix ruff issue * feat(oauth): implement OAuth * feat(invoke-message): refactor message handling and introduce InvokeMessage class * feat(plugin-oauth): add credential_id and credential_type to tool parameters * feat(plugin-oauth): add credential_id and credential_type to tool parameters * chore: update dify_plugin version to 0.5.0b4 and clean up github.yaml * chore: update plugin version to 0.1.2 in manifest.yaml * feat(session): session context and tool backwards invocation credential support * feat(oauth): session context and tool backwards invocation credential support * feat: update README and requirements for OAuth support in version 0.4.2 * feat: add .gitignore to exclude IDE files and secret keys * chore: apply ruff * feat: bump version to 0.4.2b1 * feat: update GitHub plugin configuration for OAuth support and improve credential handling * feat: update .gitignore to exclude dify plugin files and public keys * feat: fix credential validation for GitHub API and bump version to 0.2.1 * feat: update GitHub plugin to support multiple access tokens and bump version to 0.2.5 * chore: apply ruff * feat: add ToolProviderOAuthError for improved OAuth error handling in GitHub plugin * chore: apply ruff * chore: bump version to 0.4.2 * chore: update examples sdk version to 0.4.2 * fix: thread deadlock in PluginRunner when running tests without gevent monkey patching * feat: add support for refreshing OAuth credentials in Plugin and GitHub provider * feat: refactor OAuth credential handling to return structured OAuthCredentials object * apply ruff * feat: refactor OAuth credential handling to use ToolOAuthCredentials for improved structure * feat: reorganize imports in __init__.py for improved clarity and structure * feat: add Microsoft To Do plugin for refresh token example * chore: apply ruff * fix: update author in GitHub configuration and clean up Microsoft To Do schema * chore: bump version to 0.4.2b2 in pyproject.toml * feat: update Microsoft To Do plugin to handle OAuth token encoding and version bump * feat:remove inelegant example * chore: update dify_plugin version to 0.4.2 * chore: bump version to 0.4.2 in pyproject.toml --------- Co-authored-by: Yeuoly <admin@srmxy.cn>
129 lines
5.5 KiB
Python
129 lines
5.5 KiB
Python
import json
|
|
from collections.abc import Generator
|
|
from datetime import datetime
|
|
from typing import Any
|
|
|
|
import requests
|
|
|
|
from dify_plugin import Tool
|
|
from dify_plugin.entities.provider_config import CredentialType
|
|
from dify_plugin.entities.tool import ToolInvokeMessage
|
|
from dify_plugin.errors.model import InvokeError
|
|
|
|
|
|
class GithubRepositoryPullsTool(Tool):
|
|
def _invoke(self, tool_parameters: dict[str, Any]) -> Generator[ToolInvokeMessage, None, None]:
|
|
"""
|
|
invoke tools
|
|
"""
|
|
owner = tool_parameters.get("owner", "")
|
|
repo = tool_parameters.get("repo", "")
|
|
state = tool_parameters.get("state", "open")
|
|
per_page = tool_parameters.get("per_page", 10)
|
|
sort = tool_parameters.get("sort", "created")
|
|
direction = tool_parameters.get("direction", "desc")
|
|
|
|
credential_type = self.runtime.credential_type
|
|
|
|
if not owner:
|
|
yield self.create_text_message("Please input owner")
|
|
return
|
|
if not repo:
|
|
yield self.create_text_message("Please input repo")
|
|
return
|
|
|
|
if credential_type == CredentialType.API_KEY and "access_tokens" not in self.runtime.credentials:
|
|
yield self.create_text_message("GitHub API Access Tokens is required.")
|
|
return
|
|
|
|
if credential_type == CredentialType.OAUTH and "access_tokens" not in self.runtime.credentials:
|
|
yield self.create_text_message("GitHub OAuth Access Tokens is required.")
|
|
return
|
|
|
|
access_token = self.runtime.credentials.get("access_tokens")
|
|
try:
|
|
headers = {
|
|
"Content-Type": "application/vnd.github+json",
|
|
"Authorization": f"Bearer {access_token}",
|
|
"X-GitHub-Api-Version": "2022-11-28",
|
|
}
|
|
s = requests.session()
|
|
api_domain = "https://api.github.com"
|
|
url = f"{api_domain}/repos/{owner}/{repo}/pulls"
|
|
|
|
params = {"state": state, "per_page": per_page, "sort": sort, "direction": direction}
|
|
|
|
response = s.request(
|
|
method="GET",
|
|
headers=headers,
|
|
url=url,
|
|
params=params,
|
|
)
|
|
|
|
if response.status_code == 200:
|
|
response_data = response.json()
|
|
|
|
pulls = []
|
|
for pull in response_data:
|
|
pull_info = {
|
|
"number": pull.get("number", 0),
|
|
"title": pull.get("title", ""),
|
|
"body": (pull.get("body", "") or "")[:200] + "..."
|
|
if len(pull.get("body", "") or "") > 200
|
|
else (pull.get("body", "") or ""),
|
|
"state": pull.get("state", ""),
|
|
"url": pull.get("html_url", ""),
|
|
"user": pull.get("user", {}).get("login", ""),
|
|
"assignee": pull.get("assignee", {}).get("login", "") if pull.get("assignee") else "",
|
|
"labels": [label.get("name", "") for label in pull.get("labels", [])],
|
|
"comments": pull.get("comments", 0),
|
|
"review_comments": pull.get("review_comments", 0),
|
|
"commits": pull.get("commits", 0),
|
|
"additions": pull.get("additions", 0),
|
|
"deletions": pull.get("deletions", 0),
|
|
"changed_files": pull.get("changed_files", 0),
|
|
"mergeable": pull.get("mergeable", None),
|
|
"merged": pull.get("merged", False),
|
|
"draft": pull.get("draft", False),
|
|
"head": {
|
|
"ref": pull.get("head", {}).get("ref", ""),
|
|
"sha": pull.get("head", {}).get("sha", "")[:7],
|
|
},
|
|
"base": {
|
|
"ref": pull.get("base", {}).get("ref", ""),
|
|
"sha": pull.get("base", {}).get("sha", "")[:7],
|
|
},
|
|
"created_at": datetime.strptime(pull.get("created_at", ""), "%Y-%m-%dT%H:%M:%SZ").strftime(
|
|
"%Y-%m-%d %H:%M:%S"
|
|
)
|
|
if pull.get("created_at")
|
|
else "",
|
|
"updated_at": datetime.strptime(pull.get("updated_at", ""), "%Y-%m-%dT%H:%M:%SZ").strftime(
|
|
"%Y-%m-%d %H:%M:%S"
|
|
)
|
|
if pull.get("updated_at")
|
|
else "",
|
|
}
|
|
pulls.append(pull_info)
|
|
|
|
s.close()
|
|
|
|
if not pulls:
|
|
yield self.create_text_message(f"No {state} pull requests found in {owner}/{repo}")
|
|
else:
|
|
yield self.create_text_message(
|
|
self.session.model.summary.invoke(
|
|
text=json.dumps(pulls, ensure_ascii=False),
|
|
instruction="Summarize the GitHub pull requests in a structured format",
|
|
)
|
|
)
|
|
else:
|
|
response_data = response.json()
|
|
raise InvokeError(
|
|
f"Request failed: {response.status_code} {response_data.get('message', 'Unknown error')}"
|
|
)
|
|
except InvokeError as e:
|
|
raise e
|
|
except Exception as e:
|
|
raise InvokeError(f"GitHub API request failed: {e}") from e
|